diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 84bb1273f..68271f4fb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,6 +1,7 @@ name: Deploy on: + workflow_dispatch: pull_request: types: [labeled, synchronize] push: @@ -34,6 +35,11 @@ jobs: # Environments a PR label is allowed to target (development only). ALLOWED='["paseoli.dev","paseo.fyi"]' case "$EVENT_NAME" in + workflow_dispatch) + echo 'environments=["westendli.dev"]' >> "$GITHUB_OUTPUT" + echo 'smoke_environments=["westendli.dev"]' >> "$GITHUB_OUTPUT" + echo "ref=$GITHUB_SHA" >> "$GITHUB_OUTPUT" + ;; release) echo 'environments=["paseo.li","testnet.li"]' >> "$GITHUB_OUTPUT" echo "ref=$RELEASE_TAG" >> "$GITHUB_OUTPUT" @@ -75,6 +81,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ needs.plan.outputs.ref || github.sha }} - uses: ./.github/actions/setup-node @@ -117,7 +125,7 @@ jobs: env: VITE_APP_URL: ${{ vars.APP_URL }} VITE_APP_DEBUG: ${{ vars.APP_DEBUG }} - VITE_COMMIT_SHA: ${{ github.sha }} + VITE_COMMIT_SHA: ${{ needs.plan.outputs.ref || github.sha }} VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} VITE_METRICS: ${{ secrets.VITE_METRICS }} VITE_NETWORKS: ${{ vars.NETWORKS }} diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index e28bd0b04..d2b6a636e 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -143,11 +143,79 @@ reloads the whole server configuration. `nginx -t` must pass before reload; a fa operator repair but does not reload the running service. This is not an atomic rollback or a full provisioning path. After frontend upload, the opted-in job performs a public read-only GET to + `https:///__dotli-identity/paseo/attester`, matching its environment. It requires successful HTTP status and a JSON object containing a 32-byte hex `attester`; frontend HTML with status 200 fails. No authentication challenge, token, or username is created by the smoke check. Unset `DEPLOY_NGINX` to return to dist-only CI; this does not remove an already installed proxy. +## Qualify and deploy Chat on paseo.fyi + +Chat-specific browser integration belongs to `paritytech/dotli-community#255`, head `feat/chat-v2-host-runtime`, base +`feat/pvm-wasm`. Keep that base and forward changes through Seity #287 into the deploy integration #291, +`feat/jam-peer-transport-on-seity` (base `feat/chat-seity-profile`). Only #291 carries `deploy: paseo.fyi`; never put +that label on #238, #185, #255, #287, or #290. Updating these branches does not merge their feature PRs into their +bases. + +Each browser layer must vendor a matching client/host package set from its corresponding native layer: + +| Browser layer | Native host source | +| ----------------------- | --------------------------------------------------------- | +| #185 PolkaVM runtime | `host-rust-core#540`, `feat/pvm-app-runtime` | +| #255 Chat | `host-rust-core#709`, `feat/chat-v2-product-authority` | +| #287 Seity profiles | `host-rust-core#1001`, `feat/chat-seity-profile` | +| #290 JAM PeerTransport | `host-rust-core#1010`, `feat/pvm-peer-transport` | +| #291 Deploy integration | `host-rust-core#1011`, `feat/jam-peer-transport-on-seity` | + +Keep #291 and native #1011 integration-only: merge their refreshed Seity and PeerTransport parents with `--no-ff`, then +refresh the matching vendored packages. Never copy Chat, Seity, or PeerTransport APIs into a lower layer. + +Before publishing the Chat layer: + +1. Build `@parity/truapi` and `@parity/truapi-host` from the same committed `host-rust-core#709` source, including + codegen and the browser WASM build. Version `0.17.0` alone is not proof of the method-12 native Chat actor API. + Replace the two vendored package archives together, retain `@parity/truapi=file:../truapi` in the vendored host + package, and update `vendor/truapi-host.lock.json` with the actual source and WASM revision, archive SHA-256 values, + the hash of `vendor/truapi/dist/generated/client.js`, and the uncompressed + `vendor/truapi-host/dist/wasm/web/truapi_server_bg.wasm` hash. If package dependency metadata changes, refresh + `package-lock.json` with Node 26/npm 12 and `npm install`; otherwise retain the existing lock. Never invent pins. +2. Run the repository quality gate against the candidate head and verify the vendored generated client exposes + `account.deviceChat` (method 12), `MainPurseChatPayment` review, private storage slots through `NativeChatProducts`, + and per-product platform callbacks on the shared signing runtime. The independent PolkaVM renderer/runtime asset lock + is not a substitute for the Host WASM pin. +3. Use a debug build with `VITE_NETWORKS=paseo-next-v2`. Confirm People genesis + `0x4a2b5b737de1da59e209b0000a876ec2fa20035dc34fd292a848da32d255ad48`, Coinage instance `0` (`pUSD`, six chain + decimals), and bare identity suffix `paseo`. Inspect the configured chain metadata rather than inferring an asset + from a UI name. The browser uses the inherited experimental wallet, not a product-owned wallet; it does not claim + hardware-backed spending approval. +4. In the actual browser surface, qualify invitation/acceptance, text and attachments, then a rejected payment. Every + spend must show the exact requesting product, recipient identity, amount, maximum debit, chain, asset instance and + operation. A prior Chat grant must not skip this review. Only an explicitly authorized real-funds exercise may + approve a payment; check actual settlement in both directions, not merely a sent message. +5. Close the product connection while keeping the page core's wallet lease open; receive in the background. Products and + host controls lease the same native core; changing the page product retires the old signing authority before + acquiring its replacement. Reload and verify authorized native Chat devices resume without prompting. Verify pending + payments reconcile rather than being displayed as cleared. Move the wallet to a competing tab: the former owner must + stop its worker and release custody before the new tab can sign. Concurrent custody attempts must fail unavailable, + not create a second signer or overwrite inventory. Test storage/crypto failures in an isolated profile, never by + clearing an existing wallet's storage. The wallet owner is exclusive across host subdomains/tabs. Private core + records are authenticated-encrypted in the root-origin store; immutable attachment source Blobs remain host-private + but are not encrypted at rest, matching the SDK source store's existing policy. + +After qualifying each source layer, forward both #287 and #290 into #291 and rebuild its matching native #1011 package +set. Run the quality gate and browser qualification again on the final #291 candidate. Verify the repository, PR number, +head, base, vendor provenance, and deployment label before publishing the approved candidate to **#291's existing head +branch**. Its `pull_request/synchronize` event selects `paseo.fyi` from that label and deploys the PR head SHA after the +quality gate. Confirm that no other deployment label is present before triggering a synchronization. Observe both +published-product and TrUAPI smoke jobs, then repeat the Chat surface checks on paseo.fyi with the separately qualified, +payment-capable `echat.paseo` product release. An older `egui-chat` build is not a substitute for the current product or +evidence that payments work. + +Do not use `workflow_dispatch` for this operation: this workflow routes manual dispatch to **westendli.dev**, not +paseo.fyi. Do not fall back to another environment if paseo.fyi qualification or deployment fails. The wallet's +same-origin identity proxy must already be configured, or its separately authorized `DEPLOY_NGINX` opt-in must target +`fyi-paseo` as documented above. + ## Checking what is deployed Every origin serves its own build's `host_version.json` at the root: diff --git a/README.md b/README.md index 2797dbd9e..b6d6101fb 100644 --- a/README.md +++ b/README.md @@ -248,10 +248,12 @@ be tested without publishing a manifest. Custom messages (`ChatMessageContent::Custom`) render live: when a custom message cell scrolls into view, the panel asks the product to draw it through the Renderer service (`renderer.render`, with a `ChatMessage` render context) and renders -the streamed tree with the host's own design system (`src/chat/custom-renderer.ts`). The tree is a closed vocabulary of -layouts and design tokens, so a product can never inject markup, styles, or URLs. Button taps and text-field edits -inside a rendered tree flow back on `renderer.action_subscribe`; taps on `Actions`-content buttons flow back as -`ActionTriggered` chat actions. +the streamed tree with the host's Solid components (`packages/ui/src/components/chat/CustomMessage.tsx` and +`CustomNode.tsx`). The tree is a closed vocabulary of layouts and design tokens, so a product can never inject markup, +styles, or URLs. Button taps and text-field edits inside a rendered tree flow back on `renderer.action_subscribe`; taps +on `Actions`-content buttons flow back as `ActionTriggered` chat actions. Replacing a streamed tree aborts its image +loads and revokes its object URLs; scrolling a message out of view or closing the panel releases its render subscription +and tree resources. ### App iframe model @@ -444,6 +446,10 @@ scenarios exercise a fresh visit without opting in. On production `dot.li`, the **Save & Apply** first. An existing saved choice, including an opt-out on a testnet, remains authoritative. The site default applies only when no valid preference has been saved. +The `echat` smoke stays signed out: it cancels the initial sign-in request, uses the guest's Retry button to open a +fresh host prompt, cancels again, and checks redraw and resize. An idle, demand-driven UI need not publish continuous +update telemetry. The game scenarios retain their continuous rendering, audio, and input checks. + ```bash cd apps/host DOTLI_SMOKE_ROOT=paseo.fyi DOTLI_WEBGPU=1 npm run test:smoke:products -- --output=test-results/products @@ -550,6 +556,22 @@ native resource-allocation API and require an explicit request confirmation; nat exposes allocation outcomes, not remaining quota, balances, amounts or fees. Results are labeled as last observed outcomes, and uncertain results are not retried automatically. +Native Chat uses the wallet-owned main purse, private device records and a durable product index in the protocol +origin's IndexedDB. Closing a product connection does not stop receiving while the page's wallet core remains alive. A +page-product change retires the previous signer and releases its custody before starting the replacement; reload +restores only previously authorized devices, without prompting for fresh Chat authority in the background. Each payment +requires a new host review of the authenticated product and recipient, exact amount, maximum debit including fees, +selected chain and Coinage asset, and payment operation. Chat or automatic-signing grants never approve spending. +Private core records are authenticated-encrypted at rest; immutable attachment source Blobs are private to the trusted +host but are not encrypted at rest. They never enter product storage or the product RPC interface. + +Contacts are read from the active native wallet and People-chain binding, never from a product-provided roster. The +Solid host picker cancels when its connection closes or the session, roster, wallet or network changes, and revalidates +a selection before returning a contact handle. Product prompts have connection-owned modal scopes; authentication, +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. + Use the existing **List**, **Timeline**, and **Resolution** tabs for activity and diagnostics. Wallet does not duplicate their event viewer or capture controls. @@ -561,14 +583,16 @@ deletion controls are confined to Recovery. **Import / replace test wallet** accepts checksum-valid English BIP-39 phrases of 12, 15, 18, 21 or 24 words, without a passphrase or custom derivation path. It uses native Polkadot host/Substrate derivation, not Bitcoin/Ethereum seed -derivation. Importing an exported phrase restores the same account keys on the same network, but not permissions; use -**Check username** to rediscover its registered name. Back up the previous test wallet before replacing it. Successful -import replaces the shared wallet for trusted product hosts, clears wallet-bound experimental session/signing grants, -activates the imported wallet and reloads open tabs; Mobile pairing and grants remain separate. - -**Delete test wallet** requires confirmation and removes the shared wallet's stored entropy, experimental -session/signing grants and this origin's preserved legacy copy. Without a recovery phrase backup, deleting the wallet or -clearing site data permanently loses access. +derivation. Importing an exported phrase restores the same account keys on the same network, but not permissions; its +registered username is looked up automatically. Back up the previous test wallet before replacing it. Successful import +replaces the shared wallet for trusted product hosts, clears wallet-bound experimental session/signing grants, activates +the imported wallet and reloads open tabs; Mobile pairing and grants remain separate. + +**Delete test wallet** requires confirmation and removes the shared wallet's stored entropy and this origin's preserved +legacy copy, while retiring experimental session/signing grants. Wallet-scoped purse and Chat records are retained +separately, not silently erased by identity replacement or deletion; restoring the same identity still requires fresh +permissions. A recovery phrase restores identity keys, not a backup of private purse or Chat records. Clearing site data +can therefore destroy private state even when the phrase is backed up. Only one tab of a browser profile runs the test wallet at a time, because two tabs starting their own wallet cores would claim allowances twice and overwrite each other's state. Opening an app with the test wallet in another tab moves it diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 7a96fe355..d8c3e7091 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -10,10 +10,24 @@ outbound license. The vendored `@useragent-kit/polkavm-runtime` browser artifact notices, per-file hashes, and source provenance ship beside the runtime. Build-time-only tooling under source-available FSL-1.1-MIT terms is not redistributed as part of the application. +The vendored `@parity/truapi` client is MIT-licensed. The `@parity/truapi-host` distribution is `MIT AND AGPL-3.0-only`, +not MIT-only: its Rust signing runtime/WASM includes the native Chat, HOP and Coinage implementations. Both packages +come from +[host-rust-core revision `437a46c5af88b3c4a962d763f8fa5732e9c48183`](https://github.com/paritytech/host-rust-core/commit/437a46c5af88b3c4a962d763f8fa5732e9c48183). +Archive and installed artifact hashes are recorded in `vendor/truapi-host.lock.json`, including the local dependency +override. The Host's `LICENSE`, `LICENSE-AGPL-3.0` and `NOTICE` are retained in `vendor/truapi-host/`; the notice +identifies the adapted components and their source revisions. Corresponding Source for redistribution must include that +exact Host source, its component provenance and build instructions, plus any local modifications; a repository URL alone +does not supply unpublished changes. + > Generated from the resolved dependency tree (841 distinct third-party packages) by `scripts/third-party-notices.ts`. > Platform-specific binary packages (for example `*-darwin-arm64`, `@esbuild/*`, `@rolldown/*`) reflect the build host; > other platforms resolve their own equivalents under the same licenses. Regenerate after dependency changes. +## MIT AND AGPL-3.0-only + +@parity/truapi-host + ## MIT @apideck/better-ajv-errors, @astrojs/astro2tsx, @astrojs/check, @astrojs/compiler-binding, @@ -62,8 +76,8 @@ FSL-1.1-MIT terms is not redistributed as part of the application. @esbuild/darwin-arm64, @eslint-community/eslint-utils, @eslint-community/regexpp, @eslint/js, @img/colour, @jridgewell/gen-mapping, @jridgewell/remapping, @jridgewell/resolve-uri, @jridgewell/source-map, @jridgewell/sourcemap-codec, @jridgewell/trace-mapping, @keyv/bigmap, @keyv/serialize, @napi-rs/wasm-runtime, -@noble/ciphers, @noble/curves, @noble/hashes, @oslojs/encoding, @oxc-project/types, @parity/truapi, @parity/truapi-host, -@pkgr/core, @polkadot-api/cli, @polkadot-api/codegen, @polkadot-api/ink-contracts, @polkadot-api/json-rpc-provider, +@noble/ciphers, @noble/curves, @noble/hashes, @oslojs/encoding, @oxc-project/types, @parity/truapi, @pkgr/core, +@polkadot-api/cli, @polkadot-api/codegen, @polkadot-api/ink-contracts, @polkadot-api/json-rpc-provider, @polkadot-api/json-rpc-provider-proxy, @polkadot-api/known-chains, @polkadot-api/logs-provider, @polkadot-api/merkleize-metadata, @polkadot-api/metadata-builders, @polkadot-api/metadata-compatibility, @polkadot-api/observable-client, @polkadot-api/pjs-signer, @polkadot-api/raw-client, @polkadot-api/raw-tx-creator, diff --git a/apps/host/src/errors.ts b/apps/host/src/errors.ts index e7c758fd9..e4d7c1263 100644 --- a/apps/host/src/errors.ts +++ b/apps/host/src/errors.ts @@ -1,7 +1,7 @@ // Copyright 2026 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: AGPL-3.0-only -import { WALLET_OWNER_BUSY_ERROR } from '@dotli/protocol'; +import { CORE_CUSTODY_BUSY_ERROR, WALLET_OWNER_BUSY_ERROR } from '@dotli/protocol'; import { ProtocolFatalError, ProtocolInitFailedError } from '@dotli/protocol'; import { getActiveServicesConfig, BACKEND_LABELS } from '@dotli/config'; @@ -184,7 +184,7 @@ function classifyError( // compile error rather than a silently unkeyed error page. const msg = err instanceof Error ? err.message : String(err); - if (err instanceof Error && err.name === WALLET_OWNER_BUSY_ERROR) { + if (err instanceof Error && (err.name === WALLET_OWNER_BUSY_ERROR || err.name === CORE_CUSTODY_BUSY_ERROR)) { return walletInOtherTab(); } if (err instanceof ProtocolFatalError) { diff --git a/apps/host/tests/smoke/polkavm-products.spec.ts b/apps/host/tests/smoke/polkavm-products.spec.ts index 0c7502580..dfc018114 100644 --- a/apps/host/tests/smoke/polkavm-products.spec.ts +++ b/apps/host/tests/smoke/polkavm-products.spec.ts @@ -11,7 +11,7 @@ interface ProductSmoke { clickPosition?: { readonly x: number; readonly y: number }; audio: boolean; nonzeroAudio: boolean; - interaction?: 'gameplay-pointer-capture' | 'pointer-motion' | 'host-frame-handshake'; + interaction?: 'gameplay-pointer-capture' | 'pointer-motion' | 'host-frame-handshake' | 'host-sign-in'; } const products: readonly ProductSmoke[] = [ @@ -39,6 +39,17 @@ const products: readonly ProductSmoke[] = [ nonzeroAudio: true, interaction: 'gameplay-pointer-capture', }, + { + label: 'echat', + profile: 'tri2d', + keys: [], + scheduling: 'demand-driven', + // The signed-out guest's Retry button reopens the host sign-in prompt. + clickPosition: { x: 880, y: 132 }, + audio: false, + nonzeroAudio: false, + interaction: 'host-sign-in', + }, { label: 'egui-app-lab', profile: 'tri2d', @@ -111,6 +122,21 @@ async function waitForRuntimeReady(page: Page, body: Locator, canvas: Locator, l throw new Error(`${label}: runtime did not become ready within 180s\n${lastText}`); } +async function cancelSignIn(page: Page, canvas: Locator): Promise { + const signIn = page.locator('#auth-modal-backdrop'); + await expect(signIn).toBeVisible({ timeout: 30_000 }); + const responsesBefore = await counter(canvas, 'data-polkavm-host-frame-responses'); + await signIn.getByRole('button', { name: 'Cancel', exact: true }).click(); + await expect(signIn).toBeHidden(); + await expect + .poll(() => counter(canvas, 'data-polkavm-host-frame-responses'), { timeout: 30_000 }) + .toBeGreaterThan(responsesBefore); + const framesAfterResponse = await counter(canvas, 'data-polkavm-frames'); + await expect + .poll(() => counter(canvas, 'data-polkavm-frames'), { timeout: 30_000 }) + .toBeGreaterThan(framesAfterResponse); +} + async function smokeProduct(page: Page, product: ProductSmoke): Promise> { const productUrl = `https://${product.label}.${root}/`; const iframeSelector = `iframe[src*="${product.label}.app.${root}"]`; @@ -172,6 +198,9 @@ async function smokeProduct(page: Page, product: ProductSmoke): Promise { + it('is not reported as an unreachable domain with connectivity advice', () => { + // Shaped as it arrives over postMessage: only message and name survive. + const refused = new Error('The test wallet is active in another tab. Close it before opening it here.'); + refused.name = CORE_CUSTODY_BUSY_ERROR; + + for (const isP2p of [true, false]) { + const described = describeError(refused, isP2p); + expect(described).toMatchObject({ + kind: 'wallet-in-other-tab', + title: ERROR_TITLES.WALLET_IN_OTHER_TAB, + recovery: 'reload', + tips: [], + }); + } + }); +}); diff --git a/apps/protocol/src/core-custody.ts b/apps/protocol/src/core-custody.ts new file mode 100644 index 000000000..7a2f5ab08 --- /dev/null +++ b/apps/protocol/src/core-custody.ts @@ -0,0 +1,280 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +import { CORE_CUSTODY_BUSY_ERROR, type CoreCustodyOperation } from '@dotli/protocol'; +import { withSharedWalletRevision } from './wallet-storage.js'; + +export const CORE_CUSTODY_DB_NAME = 'dotli-native-core-custody'; +const STORE = 'records'; +const KEY = 'encryption-key'; +const CUSTODY_LOCK = 'dotli:native-core-custody'; +/** + * The test-wallet owner lease moves the wallet between tabs; custody only + * waits while the previous owner finishes stopping its runtimes. + */ +const CUSTODY_WAIT_MS = 10_000; +let lease: + | { + token: string; + revision: string | null; + released: Promise; + release(): void; + } + | undefined; +let acquiring = false; +let pageActive = true; +let pageLifetime = 0; + +// A lease belongs to this host iframe's parent, not to a product or a TTL. +// Page destruction releases Web Locks even if JavaScript never runs cleanup. +window.addEventListener('pagehide', () => { + pageActive = false; + pageLifetime++; + lease?.release(); + lease = undefined; +}); +window.addEventListener('pageshow', () => { + pageActive = true; +}); + +async function openDatabase(): Promise { + const { promise, resolve, reject } = Promise.withResolvers(); + const request = indexedDB.open(CORE_CUSTODY_DB_NAME, 1); + request.onupgradeneeded = () => request.result.createObjectStore(STORE); + let blocked = false; + request.onblocked = () => { + blocked = true; + reject(new Error('Private custody storage is blocked')); + }; + request.onerror = () => { + reject(new Error('Private custody storage is unavailable')); + }; + request.onsuccess = () => { + if (blocked) { + request.result.close(); + return; + } + resolve(request.result); + }; + return promise; +} + +function transaction( + db: IDBDatabase, + mode: IDBTransactionMode, + action: (store: IDBObjectStore) => IDBRequest, +): Promise { + const { promise, resolve, reject } = Promise.withResolvers(); + const tx = db.transaction(STORE, mode, { durability: 'strict' }); + let request: IDBRequest; + tx.oncomplete = () => { + resolve(request.result); + }; + tx.onerror = tx.onabort = () => { + reject(new Error('Private custody transaction failed')); + }; + try { + request = action(tx.objectStore(STORE)); + } catch (error) { + tx.abort(); + reject(error); + } + return promise; +} + +export async function handleCoreCustody( + operation: CoreCustodyOperation, + deadlineMs?: number, +): Promise { + if (operation.action === 'acquire') { + if (!pageActive) { + throw new Error('Private custody host is inactive'); + } + if ( + typeof navigator.locks === 'undefined' || + typeof crypto.subtle === 'undefined' || + typeof globalThis.indexedDB === 'undefined' + ) { + throw new Error('Private custody requires Web Locks, Web Crypto and IndexedDB'); + } + if (lease || acquiring) { + throw new Error('A signing runtime already owns this wallet in this page'); + } + acquiring = true; + const lifetime = pageLifetime; + const ready = Promise.withResolvers(); + const released = Promise.withResolvers(); + const waitMs = Math.max( + 0, + Math.min(CUSTODY_WAIT_MS, deadlineMs === undefined ? CUSTODY_WAIT_MS : deadlineMs - Date.now()), + ); + void navigator.locks + .request(CUSTODY_LOCK, { signal: AbortSignal.timeout(waitMs) }, async () => { + const held = Promise.withResolvers(); + await withSharedWalletRevision( + operation.walletRevision, + async () => { + // Check durable storage before giving any runtime custody authority. + const db = await openDatabase(); + db.close(); + if (!pageActive || lifetime !== pageLifetime) { + throw new Error('Private custody host closed while acquiring custody'); + } + if (deadlineMs !== undefined && Date.now() >= deadlineMs) { + throw new Error('Private custody request expired'); + } + const token = crypto.randomUUID(); + lease = { + token, + revision: operation.walletRevision, + released: released.promise, + release: () => { + held.resolve(undefined); + }, + }; + ready.resolve(token); + }, + deadlineMs, + ); + await held.promise; + }) + .catch((error: unknown) => { + if (error instanceof DOMException && (error.name === 'AbortError' || error.name === 'TimeoutError')) { + const busy = new Error('The test wallet is active in another tab. Close it before opening it here.'); + busy.name = CORE_CUSTODY_BUSY_ERROR; + ready.reject(busy); + return; + } + ready.reject(error); + }) + .finally(() => { + acquiring = false; + released.resolve(undefined); + }); + try { + return await ready.promise; + } catch (error) { + acquiring = false; + throw error; + } + } + const owner = lease; + if (operation.lease !== owner?.token) { + throw new Error('Private custody lease is unavailable'); + } + if (operation.action === 'release') { + lease = undefined; + owner.release(); + await owner.released; + return; + } + let result: Uint8Array | Blob | undefined; + await withSharedWalletRevision( + owner.revision, + async () => { + if (lease !== owner) { + throw new Error('Private custody lease changed'); + } + const db = await openDatabase(); + try { + if (operation.action === 'putSources') { + // IndexedDB commits immutable Blob snapshots without materializing an + // entire attachment as a JavaScript byte array. No names or paths persist. + await transaction(db, 'readwrite', store => { + let last: IDBRequest | undefined; + for (const source of operation.sources) { + last = store.add( + source.blob.slice(0, source.blob.size, 'application/octet-stream'), + `source:${source.sourceId}`, + ); + } + if (!last) { + throw new Error('No Chat sources supplied'); + } + return last; + }); + return; + } + if (operation.action === 'readSource') { + const blob: unknown = await transaction(db, 'readonly', store => store.get(`source:${operation.sourceId}`)); + if (blob !== undefined && !(blob instanceof Blob)) { + throw new Error('Private Chat source is corrupt'); + } + result = blob; + return; + } + if (operation.action === 'releaseSource') { + await transaction(db, 'readwrite', store => store.delete(`source:${operation.sourceId}`)); + return; + } + const storageKey = `core:${operation.key}`; + if (operation.action === 'clear') { + await transaction(db, 'readwrite', store => store.delete(storageKey)); + return; + } + const storedKey: unknown = await transaction(db, 'readonly', store => store.get(KEY)); + const stored: unknown = + operation.action === 'read' ? await transaction(db, 'readonly', store => store.get(storageKey)) : undefined; + if (operation.action === 'read' && stored === undefined) { + return; + } + let key: CryptoKey; + if (storedKey === undefined) { + if (operation.action === 'read') { + throw new Error('Private custody encryption key is missing'); + } + const existing = await transaction(db, 'readonly', store => store.count(IDBKeyRange.bound('core:', 'core;'))); + if (existing > 0) { + throw new Error('Private custody encryption key is missing'); + } + key = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']); + await transaction(db, 'readwrite', store => store.add(key, KEY)); + } else { + if ( + !(storedKey instanceof CryptoKey) || + storedKey.type !== 'secret' || + storedKey.algorithm.name !== 'AES-GCM' || + storedKey.extractable + ) { + throw new Error('Private custody encryption key is invalid'); + } + key = storedKey; + } + const additionalData = new TextEncoder().encode(storageKey); + if (operation.action === 'read') { + if (!(stored instanceof Uint8Array) || stored.length < 28) { + throw new Error('Private custody record is corrupt'); + } + // Failure is not absence: never delete/recreate an undecryptable purse or device. + result = new Uint8Array( + await crypto.subtle.decrypt( + { + name: 'AES-GCM', + iv: new Uint8Array(stored.subarray(0, 12)), + additionalData, + }, + key, + new Uint8Array(stored.subarray(12)), + ), + ); + } else { + const iv = crypto.getRandomValues(new Uint8Array(12)); + const ciphertext = new Uint8Array( + await crypto.subtle.encrypt({ name: 'AES-GCM', iv, additionalData }, key, new Uint8Array(operation.value)), + ); + const record = new Uint8Array(iv.length + ciphertext.length); + record.set(iv); + record.set(ciphertext, iv.length); + if (lease !== owner) { + throw new Error('Private custody lease changed'); + } + await transaction(db, 'readwrite', store => store.put(record, storageKey)); + } + } finally { + db.close(); + } + }, + deadlineMs, + ); + return result; +} diff --git a/apps/protocol/src/engine.ts b/apps/protocol/src/engine.ts index da6353d56..2db512550 100644 --- a/apps/protocol/src/engine.ts +++ b/apps/protocol/src/engine.ts @@ -106,6 +106,7 @@ export function createEngine(options: EngineOptions): ProtocolEngine { isSharedAuthRequestMethod(request.method) || isSharedModeRequestMethod(request.method) || request.method === 'walletStorage' || + request.method === 'coreCustody' || request.method === 'walletOwner' ) { throw new Error(`Shared storage request reached the chain engine: ${request.method}`); diff --git a/apps/protocol/src/main.ts b/apps/protocol/src/main.ts index 1aaa8495f..0e4e24dfb 100644 --- a/apps/protocol/src/main.ts +++ b/apps/protocol/src/main.ts @@ -91,8 +91,10 @@ import { createWalletOwner, isWalletOwnerOperation, type WalletOwner, + isCoreCustodyOperation, } from '@dotli/protocol'; import { handleWalletOperation, WALLET_DB_NAME, withSharedWalletRevision } from './wallet-storage.js'; +import { CORE_CUSTODY_DB_NAME, handleCoreCustody } from './core-custody.js'; import type { SWRelayRequest, SWOutbound } from './protocol-shared-worker.js'; import { PROTOCOL_APP_ERRORS } from './errors.js'; @@ -340,7 +342,7 @@ function bindSharedWalletListener(): void { if ( !isProtocolEnvelope(request) || request.kind !== 'request' || - (request.method !== 'walletStorage' && request.method !== 'walletOwner') + (request.method !== 'walletStorage' && request.method !== 'coreCustody' && request.method !== 'walletOwner') ) { return; } @@ -369,6 +371,20 @@ function bindSharedWalletListener(): void { }); return; } + if (request.method === 'coreCustody') { + if (!isCoreCustodyOperation(payload.operation)) { + throw new Error('Invalid private custody operation'); + } + const result = await handleCoreCustody(payload.operation, request.deadlineMs); + postToSource(event.source, event.origin, { + namespace: 'dotli:protocol', + kind: 'response', + id: request.id, + ok: true, + result, + }); + return; + } if (!isSharedWalletOperation(payload.operation)) { throw new Error('Invalid wallet operation'); } @@ -521,7 +537,13 @@ function getRequestedNetwork(): RequestedNetwork { async function purgeWorkerCaches(): Promise { // Throw on enumeration failure and await each delete: a silent log-and- // continue would let smoldot boot against the still-present stale DB. - const keep: Record = { dotli: true, 'dotli-sw': true, [WALLET_DB_NAME]: true, 'dotli-core': true }; + const keep: Record = { + dotli: true, + 'dotli-sw': true, + [WALLET_DB_NAME]: true, + [CORE_CUSTODY_DB_NAME]: true, + 'dotli-core': true, + }; if (typeof indexedDB === 'undefined' || typeof indexedDB.databases !== 'function') { throw new Error( 'Browser does not expose indexedDB.databases() — cannot fully purge worker caches. ' + @@ -787,6 +809,7 @@ async function initSharedWorkerMode(network: Network): Promise { isSharedAuthRequestMethod(data.method) || isSharedModeRequestMethod(data.method) || data.method === 'walletStorage' || + data.method === 'coreCustody' || data.method === 'walletOwner' ) { return; @@ -1042,6 +1065,7 @@ function bindEngineToMessages(engine: ProtocolEngine): void { isSharedAuthRequestMethod(data.method) || isSharedModeRequestMethod(data.method) || data.method === 'walletStorage' || + data.method === 'coreCustody' || data.method === 'walletOwner' ) { return; diff --git a/apps/protocol/src/protocol-shared-worker.ts b/apps/protocol/src/protocol-shared-worker.ts index 8ff80423a..7854cab17 100644 --- a/apps/protocol/src/protocol-shared-worker.ts +++ b/apps/protocol/src/protocol-shared-worker.ts @@ -463,6 +463,7 @@ async function handleRequest(port: MessagePort, request: ProtocolRequestEnvelope } case 'walletStorage': + case 'coreCustody': case 'walletOwner': throw new Error('Wallet storage is only available through the trusted protocol iframe'); diff --git a/apps/protocol/src/wallet-storage.ts b/apps/protocol/src/wallet-storage.ts index 36f11f5bc..d6c628e6f 100644 --- a/apps/protocol/src/wallet-storage.ts +++ b/apps/protocol/src/wallet-storage.ts @@ -247,7 +247,7 @@ export async function handleWalletOperation( /** Serialize verified-public-metadata writes with identity replacement/deletion. */ export async function withSharedWalletRevision( revision: string | null, - commit: () => void, + commit: () => void | Promise, deadlineMs?: number, ): Promise { if (typeof navigator.locks === 'undefined') { @@ -263,7 +263,7 @@ export async function withSharedWalletRevision( if (record === undefined || !record.enabled || record.encrypted === undefined || record.revision !== revision) { throw conflict('Wallet changed while saving its verified identity.'); } - commit(); + await commit(); } finally { db.close(); } diff --git a/package-lock.json b/package-lock.json index 981aaf3ad..7a3782261 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16093,7 +16093,7 @@ "vendor/truapi-host": { "name": "@parity/truapi-host", "version": "0.23.0", - "license": "MIT", + "license": "MIT AND AGPL-3.0-only", "dependencies": { "@noble/hashes": "^2.2.0", "@parity/truapi": "file:../truapi", diff --git a/packages/config/src/network.ts b/packages/config/src/network.ts index f01aa9989..0456ce8a1 100644 --- a/packages/config/src/network.ts +++ b/packages/config/src/network.ts @@ -44,6 +44,8 @@ export interface ChainService { export interface BulletinService extends ChainService { readonly ipfsGateways: readonly string[]; + /** Host-private HOP endpoints; never inferred from ordinary chain RPC URLs. */ + readonly hopEndpoints?: readonly string[]; } export interface ServicesConfig { @@ -54,6 +56,12 @@ export interface ServicesConfig { readonly assethub: ChainService; readonly bulletin: BulletinService; readonly people: ChainService; + /** Trusted People-chain Coinage asset; absent where payments are not configured. */ + readonly coinage?: { + readonly instanceId: number; + readonly symbol: string; + readonly decimals: number; + }; readonly dotns: DotnsContracts; } @@ -83,12 +91,14 @@ const BUILTIN_NETWORK_SERVICES: Record = { rpcs: ['wss://paseo-bulletin-next-rpc.polkadot.io'], blockTimeMs: 6000, ipfsGateways: ['https://paseo-bulletin-next-ipfs.polkadot.io'], + hopEndpoints: ['wss://paseo-hop-next-0.polkadot.io', 'wss://paseo-hop-next-1.polkadot.io'], }, people: { genesis: '0x4a2b5b737de1da59e209b0000a876ec2fa20035dc34fd292a848da32d255ad48', rpcs: ['wss://paseo-people-next-system-rpc.polkadot.io'], blockTimeMs: 2000, }, + coinage: { instanceId: 0, symbol: 'pUSD', decimals: 6 }, dotns: { DOTNS_REGISTRY: '0xf34054fd76BbF85f216cf9908226D5f0A72E50CA', DOTNS_CONTENT_RESOLVER: '0x7F74D7CD50f5a834270E2ad395a01b01891AB37d', @@ -291,6 +301,7 @@ function mergeBulletin(base: BulletinService, patch: unknown, path: string): Bul rpcs: p['rpcs'] === undefined ? base.rpcs : asStrings(p['rpcs'], `${path}.rpcs`), ipfsGateways: p['ipfsGateways'] === undefined ? base.ipfsGateways : asStrings(p['ipfsGateways'], `${path}.ipfsGateways`), + ...(base.hopEndpoints === undefined ? {} : { hopEndpoints: base.hopEndpoints }), }; } diff --git a/packages/protocol/src/client.ts b/packages/protocol/src/client.ts index b1d3371dd..eea031900 100644 --- a/packages/protocol/src/client.ts +++ b/packages/protocol/src/client.ts @@ -39,6 +39,7 @@ import { type SharedWalletResult, type SharedWalletState, } from './wallet-storage.js'; +import type { CoreCustodyOperation } from './core-custody.js'; import type { WalletOwnerOperation } from './wallet-owner.js'; interface PendingRequest { @@ -601,6 +602,7 @@ async function postRequest( needsProtocolReady = !isSharedAuthRequestMethod(method) && !isSharedModeRequestMethod(method) && method !== 'walletStorage' && + method !== 'coreCustody' && method !== 'walletOwner', ): Promise { await (needsProtocolReady ? ensureProtocolFrame() : ensureHostFrame()); @@ -739,6 +741,25 @@ export function subscribeSharedWallet(listener: (state: SharedWalletState) => vo }; } +/** Private host-shell custody channel; no product API forwards this method. */ +export async function requestCoreCustody( + operation: CoreCustodyOperation, +): Promise { + const result = await postRequest('coreCustody', { + siteId: SITE_ID, + operation, + }); + if ( + result !== undefined && + typeof result !== 'string' && + !(result instanceof Uint8Array) && + !(result instanceof Blob) + ) { + throw new Error('Invalid private custody response'); + } + return result; +} + /** Make this page the one tab running the test wallet; see `wallet-owner.ts`. */ export async function requestWalletOwner(operation: WalletOwnerOperation): Promise { const result = await postRequest('walletOwner', { diff --git a/packages/protocol/src/core-custody.ts b/packages/protocol/src/core-custody.ts new file mode 100644 index 000000000..3a9c7d947 --- /dev/null +++ b/packages/protocol/src/core-custody.ts @@ -0,0 +1,79 @@ +// Copyright 2026 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * `Error.name` of a refused `acquire`: another tab of this browser profile + * still holds the test wallet's custody. Survives the postMessage hop. + */ +export const CORE_CUSTODY_BUSY_ERROR = 'WalletCustodyBusyError'; + +/** + * Host-shell transport only. Never exposed through the product RPC bridge. + * Moving the wallet between tabs is the owner lease's job (`wallet-owner.ts`). + */ +export type CoreCustodyOperation = + | { action: 'acquire'; walletRevision: string | null } + | { action: 'release'; lease: string } + | { action: 'read'; lease: string; key: string } + | { action: 'clear'; lease: string; key: string } + | { action: 'write'; lease: string; key: string; value: Uint8Array } + | { action: 'readSource'; lease: string; sourceId: string } + | { action: 'releaseSource'; lease: string; sourceId: string } + | { + action: 'putSources'; + lease: string; + sources: { sourceId: string; blob: Blob }[]; + }; + +export function isCoreCustodyOperation(value: unknown): value is CoreCustodyOperation { + if (typeof value !== 'object' || value === null || !('action' in value)) { + return false; + } + if (value.action === 'acquire') { + return 'walletRevision' in value && (value.walletRevision === null || typeof value.walletRevision === 'string'); + } + if (!('lease' in value) || typeof value.lease !== 'string') { + return false; + } + if (value.action === 'release') { + return true; + } + if (value.action === 'readSource' || value.action === 'releaseSource') { + return 'sourceId' in value && typeof value.sourceId === 'string' && /^[a-zA-Z0-9-]{1,128}$/.test(value.sourceId); + } + if (value.action === 'putSources') { + return ( + 'sources' in value && + Array.isArray(value.sources) && + value.sources.length > 0 && + value.sources.length <= 32 && + value.sources.every( + (source: unknown) => + typeof source === 'object' && + source !== null && + 'sourceId' in source && + typeof source.sourceId === 'string' && + /^[a-zA-Z0-9-]{1,128}$/.test(source.sourceId) && + 'blob' in source && + source.blob instanceof Blob && + source.blob.size <= 0xffff_ffff, + ) + ); + } + if ( + !('key' in value) || + typeof value.key !== 'string' || + !/^[0-9a-f]{2,8192}$/.test(value.key) || + value.key.length % 2 !== 0 + ) { + return false; + } + return ( + value.action === 'read' || + value.action === 'clear' || + (value.action === 'write' && + 'value' in value && + value.value instanceof Uint8Array && + value.value.byteLength <= 32 * 1024 * 1024) + ); +} diff --git a/packages/protocol/src/index.ts b/packages/protocol/src/index.ts index 7af048282..c9a5cbd92 100644 --- a/packages/protocol/src/index.ts +++ b/packages/protocol/src/index.ts @@ -42,6 +42,7 @@ export { readSharedAuthStorage, readSharedModeStorage, resetProtocolFrame, + requestCoreCustody, requestSharedWallet, requestWalletOwner, resolveDotNameRemote, @@ -57,6 +58,7 @@ export { writeSharedAuthStorage, writeSharedModeStorage, } from './client.js'; +export { CORE_CUSTODY_BUSY_ERROR, isCoreCustodyOperation, type CoreCustodyOperation } from './core-custody.js'; export { ProtocolFatalError, ProtocolInitFailedError } from './errors.js'; export { getRequestSyncTimeoutMs, diff --git a/packages/protocol/src/messages.ts b/packages/protocol/src/messages.ts index 80a0132a0..384d80f15 100644 --- a/packages/protocol/src/messages.ts +++ b/packages/protocol/src/messages.ts @@ -4,6 +4,7 @@ import type { ChainKey, ChainPeer, ChainSyncKind } from '@dotli/resolver'; import { TIMEOUTS } from '@dotli/config'; import type { SharedWalletOperation, SharedWalletState } from './wallet-storage.js'; +import type { CoreCustodyOperation } from './core-custody.js'; import type { WalletOwnerOperation } from './wallet-owner.js'; export interface ProtocolRequestMap { @@ -27,6 +28,7 @@ export interface ProtocolRequestMap { modeStorageWrite: { siteId: string; key: string; value: string }; modeStorageClear: { siteId: string; key: string }; walletStorage: { siteId: string; operation: SharedWalletOperation }; + coreCustody: { siteId: string; operation: CoreCustodyOperation }; walletOwner: { siteId: string; operation: WalletOwnerOperation }; chainConnect: { genesisHash: string; connectionId: string }; chainSend: { connectionId: string; message: string }; diff --git a/packages/ui/src/components/overlays/SigningDialog.tsx b/packages/ui/src/components/overlays/SigningDialog.tsx index 122dc7d5e..f87be7279 100644 --- a/packages/ui/src/components/overlays/SigningDialog.tsx +++ b/packages/ui/src/components/overlays/SigningDialog.tsx @@ -22,6 +22,7 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { const titleId = `overlay-modal-title-${String(id)}`; const [password, setPassword] = createSignal(''); let input: HTMLInputElement | undefined; + let firstChoice: HTMLButtonElement | undefined; const needsPassword = (button: ModalButton): boolean => view.input !== undefined && button.variant === 'primary'; @@ -51,7 +52,7 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { }; return ( - input} onDismiss={dismiss}> + input ?? firstChoice} onDismiss={dismiss}> {icon => ( // eslint-disable-next-line solid/no-innerhtml -- trusted SVG markup from ModalView.icon, not user input @@ -72,6 +73,28 @@ export function SigningDialog(props: { entry: ModalEntry }): JSX.Element { )} {notice =>
{notice()}
}
+ + {choices => ( +
+ + {choice => ( + + )} + +
+ )} +
{spec => ( <> diff --git a/packages/ui/src/components/shell/PermissionRow.tsx b/packages/ui/src/components/shell/PermissionRow.tsx index 4ccd5466a..22f3a27a6 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: '', + ChatAuthority: + '', ChainSubmit: '', PreimageSubmit: diff --git a/packages/ui/src/host-callbacks/Chain.ts b/packages/ui/src/host-callbacks/Chain.ts index 63b9c6011..b6eef96b4 100644 --- a/packages/ui/src/host-callbacks/Chain.ts +++ b/packages/ui/src/host-callbacks/Chain.ts @@ -20,10 +20,8 @@ // request takes a new lease, which rebuilds the chain, through a backoff. import { bytesToHex } from '@parity/truapi/scale'; -import type { JsonRpcConnection, JsonRpcRequest } from '@polkadot-api/json-rpc-provider'; -import type { ChainProvider } from '@parity/truapi-host'; -import type { PlatformJsonRpcConnection } from '@parity/truapi-host'; -import type { JsonRpcProvider } from '@polkadot-api/json-rpc-provider'; +import type { JsonRpcConnection, JsonRpcRequest, JsonRpcProvider } from '@polkadot-api/json-rpc-provider'; +import type { ChainProvider, HopProvider, PlatformJsonRpcConnection } from '@parity/truapi-host'; import { getActiveServicesConfig, getBackend } from '@dotli/config'; import { chainHaltedError, @@ -301,3 +299,83 @@ export function createChainConnect(pool: ChainPool = hostChainPool): ChainProvid return Promise.resolve(toConnection(genesisHash, pool)); }; } + +/** HOP is a separate trusted transport, not a fallback chain RPC provider. */ +export function createHopProvider(): Required { + return { + allowedHopEndpoints(genesisHash) { + const bulletin = getActiveServicesConfig().bulletin; + return Promise.resolve( + bytesToHex(genesisHash) === bulletin.genesis.toLowerCase() ? [...(bulletin.hopEndpoints ?? [])] : [], + ); + }, + async connectHop(genesisHash, endpoint) { + const bulletin = getActiveServicesConfig().bulletin; + if ( + bytesToHex(genesisHash) !== bulletin.genesis.toLowerCase() || + bulletin.hopEndpoints?.includes(endpoint) !== true + ) { + throw new Error('HOP endpoint is not configured for this Bulletin chain'); + } + const socket = new WebSocket(endpoint); + const opened = Promise.withResolvers(); + const queue: string[] = []; + let stopped = false; + let wake: (() => void) | undefined; + const close = (): void => { + if (stopped) { + return; + } + stopped = true; + socket.close(); + opened.reject(new Error('HOP connection closed before opening')); + wake?.(); + }; + socket.onopen = () => { + opened.resolve(undefined); + }; + socket.onerror = close; + socket.onclose = close; + socket.onmessage = (event: MessageEvent) => { + if (stopped) { + return; + } + if (typeof event.data !== 'string') { + close(); + return; + } + queue.push(event.data); + wake?.(); + wake = undefined; + }; + await opened.promise; + return { + send(request) { + if (stopped || socket.readyState !== WebSocket.OPEN) { + throw new Error('HOP connection is closed'); + } + socket.send(request); + }, + async *responses() { + try { + while (!stopped) { + const response = queue.shift(); + if (response !== undefined) { + yield response; + continue; + } + const next = Promise.withResolvers(); + wake = () => { + next.resolve(undefined); + }; + await next.promise; + } + } finally { + close(); + } + }, + close, + }; + }, + }; +} diff --git a/packages/ui/src/host-callbacks/Contacts.ts b/packages/ui/src/host-callbacks/Contacts.ts new file mode 100644 index 000000000..a1a556394 --- /dev/null +++ b/packages/ui/src/host-callbacks/Contacts.ts @@ -0,0 +1,250 @@ +import { blake2b } from '@noble/hashes/blake2.js'; +import type { Bytes32 } from '@parity/truapi'; +import { bytesToHex, hexToBytes } from '@parity/truapi/scale'; +import type { + ContactsPlatform, + CoreStorage, + CoreStorageKey, + NativeChatContactsSnapshot, + 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'; + +const HEX32 = /^0x[0-9a-f]{64}$/; + +type ContactsRuntime = Pick; + +type ContactSnapshot = Omit & { + contacts: { peerIdentity: Bytes32; username?: string }[]; +}; + +/** One immutable signing-runtime/wallet/People binding, shared by its providers. */ +export class NativeChatContactsDirectory { + private binding?: { + runtime: ContactsRuntime; + walletPublicKey: string; + genesisHash: string; + }; + private generation = new AbortController(); + private disposed = false; + private readonly isCurrent: () => boolean; + + constructor(isCurrent: () => boolean) { + this.isCurrent = isCurrent; + } + + bind(runtime: ContactsRuntime, walletPublicKey: string, genesisHash: string): void { + if (this.binding !== undefined || this.disposed) { + throw new Error('Chat contacts runtime is already bound or disposed'); + } + assertHex32(walletPublicKey); + assertHex32(genesisHash); + this.binding = { runtime, walletPublicKey, genesisHash }; + } + + get signal(): AbortSignal { + this.assertCurrent(); + return this.generation.signal; + } + + invalidate(): void { + if (this.disposed) { + return; + } + this.generation.abort(blockingModalAbortError('Chat contacts changed')); + this.generation = new AbortController(); + this.binding?.runtime.notifyContactsChanged(); + } + + dispose(): void { + if (this.disposed) { + return; + } + this.disposed = true; + this.generation.abort(blockingModalAbortError('Chat contacts runtime closed')); + } + + async snapshot(signal: AbortSignal): Promise { + this.assertCurrent(); + throwIfAborted(signal); + const binding = this.binding; + if (binding === undefined) { + throw new Error('Chat contacts signing session is unavailable'); + } + const snapshot = await abortable(binding.runtime.getNativeChatContacts(), signal); + this.assertCurrent(); + throwIfAborted(signal); + if (snapshot.walletPublicKey !== binding.walletPublicKey || snapshot.genesisHash !== binding.genesisHash) { + throw new Error('Chat contacts do not belong to the active wallet and People network'); + } + assertContactSnapshot(snapshot); + return snapshot; + } + + private assertCurrent(): void { + if (this.disposed || !this.isCurrent()) { + throw blockingModalAbortError('Chat contacts session changed'); + } + } + + /** Observe only trusted typed keys, never encrypted Rust storage values. + * The native getter shares the writer's lock and cannot read pre-commit state. + */ + observeStorage(storage: CoreStorage): CoreStorage { + const mutate = async (key: CoreStorageKey, operation: () => Promise): Promise => { + if (!affectsContacts(key)) { + return operation(); + } + this.invalidate(); + try { + await operation(); + } finally { + this.invalidate(); + } + }; + return { + ...storage, + writeCoreStorage: (key, value) => mutate(key, () => storage.writeCoreStorage(key, value)), + clearCoreStorage: key => mutate(key, () => storage.clearCoreStorage(key)), + }; + } +} + +function affectsContacts(key: CoreStorageKey): boolean { + return ( + key.tag === 'NativeChatDevice' || + key.tag === 'NativeChatProducts' || + key.tag === 'PermissionAuthorization' || + key.tag === 'ProductManifest' || + key.tag === 'AuthSession' + ); +} + +function assertHex32(value: string): void { + if (typeof value !== 'string' || !HEX32.test(value)) { + throw new Error('Expected a canonical 32-byte contact identifier'); + } +} + +function assertContactSnapshot(snapshot: NativeChatContactsSnapshot): asserts snapshot is ContactSnapshot { + for (const contact of snapshot.contacts) { + assertHex32(contact.peerIdentity); + if (contact.username !== undefined && typeof contact.username !== 'string') { + throw new Error('Invalid native Chat contact name'); + } + } +} + +function abortable(pending: Promise, signal: AbortSignal): Promise { + const { promise, resolve, reject } = Promise.withResolvers(); + const abort = (): void => { + reject(blockingModalAbortError(signal.reason)); + }; + signal.addEventListener('abort', abort, { once: true }); + void pending.then( + value => { + signal.removeEventListener('abort', abort); + if (signal.aborted) { + abort(); + } else { + resolve(value); + } + }, + (error: unknown) => { + signal.removeEventListener('abort', abort); + reject(error); + }, + ); + if (signal.aborted) { + signal.removeEventListener('abort', abort); + abort(); + } + return promise; +} + +export function createContactsPlatform( + directory: NativeChatContactsDirectory, + modalScope: BlockingModalScope, +): { callbacks: Required; dispose(): void } { + const lifetime = new AbortController(); + const operationSignal = (): AbortSignal => AbortSignal.any([lifetime.signal, directory.signal]); + return { + dispose() { + lifetime.abort(blockingModalAbortError('Contact picker host closed')); + }, + callbacks: { + async contacts(lookup) { + assertHex32(lookup.handleKey); + for (const handle of lookup.handles) { + assertHex32(handle); + } + const signal = operationSignal(); + const snapshot = await directory.snapshot(signal); + const wanted = new Set(lookup.handles); + const matches = new Map(); + const key = hexToBytes(lookup.handleKey); + for (const contact of snapshot.contacts) { + const handle = bytesToHex(blake2b(hexToBytes(contact.peerIdentity), { key, dkLen: 32 })); + if (wanted.has(handle)) { + matches.set(handle, contact.peerIdentity); + } + } + throwIfAborted(signal); + return { + accounts: lookup.handles.map(handle => matches.get(handle)), + }; + }, + async pickContact(product) { + // Capture before enqueue: switching identity while waiting must not open + // this product's old request under the replacement wallet. + const signal = operationSignal(); + return abortable( + modalScope.enqueue(async queueSignal => { + const activeSignal = AbortSignal.any([signal, queueSignal]); + const snapshot = await directory.snapshot(activeSignal); + if (snapshot.contacts.length === 0) { + return { tag: 'NoContacts' as const }; + } + const selected = await showContactPicker(product, snapshot.contacts, activeSignal); + throwIfAborted(activeSignal); + if (selected === undefined) { + return { tag: 'Dismissed' as const }; + } + const current = await directory.snapshot(activeSignal); + if (!current.contacts.some(contact => contact.peerIdentity === selected)) { + throw new Error('The selected Chat contact is no longer available'); + } + return { tag: 'Picked' as const, value: { account: selected } }; + }), + signal, + ); + }, + }, + }; +} + +async function showContactPicker( + product: ProductContext, + contacts: ContactSnapshot['contacts'], + signal: AbortSignal, +): Promise { + const { result } = await presentModal( + { + title: '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' }], + dismissOnBackdrop: true, + dismissResult: 'dismissed', + fallbackResult: 'dismissed', + }, + signal, + ); + return result === 'dismissed' ? undefined : result; +} diff --git a/packages/ui/src/host-callbacks/SessionStore.ts b/packages/ui/src/host-callbacks/SessionStore.ts index b0357beb1..3f397b2f3 100644 --- a/packages/ui/src/host-callbacks/SessionStore.ts +++ b/packages/ui/src/host-callbacks/SessionStore.ts @@ -13,6 +13,7 @@ import { writeSharedAuthStorage, requestSharedWallet, subscribeSharedWallet, + requestCoreCustody, type SharedWalletState, } from '@dotli/protocol'; @@ -349,35 +350,88 @@ export async function emitPersistedSessionUiState(): Promise { }); } -export function createSessionStoreAdapters(): CoreStorage { +export function createSessionStoreAdapters(custodyLease?: string): CoreStorage { // Capture the mode for the lifetime of these callbacks. Switching modes // reloads the page; pending writes must not cross into the other identity. const experimental = isExperimentalWalletActive(); const generation = experimental ? localWalletStorageGeneration() : null; + const custodyKey = (key: CoreStorageKey): string => { + if ( + !experimental || + custodyLease === undefined || + custodyLease === '' || + walletMutationPending || + generation !== localWalletStorageGeneration() + ) { + throw new Error('Private wallet custody is unavailable or changed'); + } + const encoded = hexNoPrefix(encodeCoreStorageKey(key)); + // These slots carry their own immutable wallet/network scope, unlike grants. + switch (key.tag) { + case 'MainPurseCoinage': + case 'NativeChatDevice': + case 'NativeChatFileChunk': + case 'NativeChatProducts': + case 'DeviceEncryptionKey': + return encoded; + case 'AuthSession': + case 'PairingDeviceIdentity': + case 'PermissionAuthorization': + case 'AllowanceKeys': + case 'LastProcessedPairingStatement': + case 'AutoSigningKey': + case 'AutoSigningKeys': + case 'RingVrfRegistry': + case 'StatementRenewalTargets': + case 'ProductSubtree': + case 'SsoResponderRequestLedger': + case 'ProductManifest': + return hexNoPrefix(new TextEncoder().encode(`${generation}:`)) + encoded; + } + }; return { async readCoreStorage(key) { - return readCoreStorageValue(key, experimental, generation); + if (experimental) { + const result = await requestCoreCustody({ + action: 'read', + lease: custodyLease ?? '', + key: custodyKey(key), + }); + if (result !== undefined && !(result instanceof Uint8Array)) { + throw new Error('Invalid private custody record'); + } + return result; + } + return readCoreStorageValue(key); }, async writeCoreStorage(key, value) { - await writeCoreStorageValue(key, value, experimental, generation); + if (experimental) { + await requestCoreCustody({ + action: 'write', + lease: custodyLease ?? '', + key: custodyKey(key), + value, + }); + return; + } + await writeCoreStorageValue(key, value); }, async clearCoreStorage(key) { - if (!experimental || generation === localWalletStorageGeneration()) { - await clearCoreStorageValue(key, experimental, generation); + if (experimental) { + await requestCoreCustody({ + action: 'clear', + lease: custodyLease ?? '', + key: custodyKey(key), + }); + return; } + await clearCoreStorageValue(key); }, }; } -async function readCoreStorageValue( - key: CoreStorageKey, - experimental = false, - generation: string | null = null, -): Promise { - if (experimental && (walletMutationPending || generation !== localWalletStorageGeneration())) { - return undefined; - } - if (key.tag === 'AuthSession' && !experimental) { +async function readCoreStorageValue(key: CoreStorageKey): Promise { + if (key.tag === 'AuthSession') { let raw: string | null; try { raw = await readSharedAuthStorage(SITE_ID, SHARED_CORE_SESSION_KEY); @@ -390,8 +444,8 @@ async function readCoreStorageValue( } return decodeStoredBytes(raw, 'shared auth session'); } - const raw = localStorage.getItem(coreLocalStorageKey(key, experimental, generation)); - return raw === null ? undefined : await decodeCoreStorageValue(key, raw, experimental, generation); + const raw = localStorage.getItem(coreLocalStorageKey(key)); + return raw === null ? undefined : await decodeCoreStorageValue(key, raw); } function decodeStoredBytes(raw: string, description: string): Uint8Array | undefined { @@ -403,45 +457,27 @@ function decodeStoredBytes(raw: string, description: string): Uint8Array | undef } } -async function writeCoreStorageValue( - key: CoreStorageKey, - value: Uint8Array, - experimental = false, - generation: string | null = null, -): Promise { - if (key.tag === 'AuthSession' && !experimental) { +async function writeCoreStorageValue(key: CoreStorageKey, value: Uint8Array): Promise { + if (key.tag === 'AuthSession') { await writeSharedAuthStorage(SITE_ID, SHARED_CORE_SESSION_KEY, bytesToHex(value)); emitLocalChange(); return; } const encoded = await encodeCoreStorageValue(key, value); - if (!experimental || (!walletMutationPending && generation === localWalletStorageGeneration())) { - localStorage.setItem(coreLocalStorageKey(key, experimental, generation), encoded); - } + localStorage.setItem(coreLocalStorageKey(key), encoded); } -async function clearCoreStorageValue( - key: CoreStorageKey, - experimental = false, - generation: string | null = null, -): Promise { - if (key.tag === 'AuthSession' && !experimental) { +async function clearCoreStorageValue(key: CoreStorageKey): Promise { + if (key.tag === 'AuthSession') { await clearSharedAuthStorage(SITE_ID, SHARED_CORE_SESSION_KEY); await writeUiStateCache({ connected: false }); emitLocalChange(); return; } - localStorage.removeItem(coreLocalStorageKey(key, experimental, generation)); + localStorage.removeItem(coreLocalStorageKey(key)); } -function coreLocalStorageKey(key: CoreStorageKey, experimental = false, generation: string | null = null): string { - if (experimental) { - return ( - EXPERIMENTAL_CORE_STORAGE_PREFIX + - (generation === null ? '' : `${generation}:`) + - hexNoPrefix(encodeCoreStorageKey(key)) - ); - } +function coreLocalStorageKey(key: CoreStorageKey): string { switch (key.tag) { case 'PairingDeviceIdentity': return `${CORE_LOCAL_STORAGE_PREFIX}pairing-device-identity`; @@ -482,6 +518,11 @@ function coreLocalStorageKey(key: CoreStorageKey, experimental = false, generati // grant expires without touching the others. case 'ProductManifest': return `${CORE_LOCAL_STORAGE_PREFIX}product-manifest:${key.value.productId}`; + case 'MainPurseCoinage': + case 'NativeChatDevice': + case 'NativeChatFileChunk': + case 'NativeChatProducts': + throw new Error('Native Chat custody requires the local signing wallet'); } } @@ -508,12 +549,7 @@ async function encodeCoreStorageValue(key: CoreStorageKey, value: Uint8Array): P return bytesToHex(value); } -async function decodeCoreStorageValue( - key: CoreStorageKey, - raw: string, - experimental = false, - generation: string | null = null, -): Promise { +async function decodeCoreStorageValue(key: CoreStorageKey, raw: string): Promise { if (!storesSecretMaterial(key)) { return decodeStoredBytes(raw, `core storage ${key.tag}`); } @@ -526,7 +562,7 @@ async function decodeCoreStorageValue( return undefined; } log.warn(`[dot.li] re-encrypting legacy plaintext core storage ${key.tag}`); - await writeCoreStorageValue(key, bytes, experimental, generation); + await writeCoreStorageValue(key, bytes); return bytes; } const bytes = decodeStoredBytes(raw.slice(ENCRYPTED_VALUE_PREFIX.length), `core storage ${key.tag}`); @@ -547,7 +583,7 @@ async function decodeCoreStorageValue( // key) or the bytes are corrupt. Drop it: returning the raw bytes // would hand ciphertext to the core as key material. log.warn(`[dot.li] dropping undecryptable core storage ${key.tag}:`, err); - localStorage.removeItem(coreLocalStorageKey(key, experimental, generation)); + localStorage.removeItem(coreLocalStorageKey(key)); return undefined; } } diff --git a/packages/ui/src/host-callbacks/UserConfirmation.ts b/packages/ui/src/host-callbacks/UserConfirmation.ts index a303c4c37..c4fc8262c 100644 --- a/packages/ui/src/host-callbacks/UserConfirmation.ts +++ b/packages/ui/src/host-callbacks/UserConfirmation.ts @@ -1,9 +1,11 @@ import type { AccountAccessReview, AccountAliasReview, + ChatAuthorityReview, CreateProofReview, CreateTransactionReview, IdentityDisclosureReview, + MainPurseChatPaymentReview, PermissionDecision, PreimageSubmitReview, ProductSubtreeReview, @@ -24,6 +26,7 @@ import type { RingLocationJunction, } from '@parity/truapi'; import { hexToBytes } from '@parity/truapi/scale'; +import { getActiveServicesConfig } from '@dotli/config'; import { showPreimageSubmitModal } from '../preimage-modal.js'; import { ERRORS } from '../errors.js'; import { createBlockingModalScope, throwIfAborted, type BlockingModalScope } from '../blocking-modal-queue.js'; @@ -110,6 +113,10 @@ function confirmationDisplay(label: string, review: ModalReview): { fields: Conf case 'IdentityDisclosure': case 'ProductSubtree': return { fields: createRequestingProductFields(review.value) }; + case 'ChatAuthority': + return { fields: createChatAuthorityFields(review.value) }; + case 'MainPurseChatPayment': + return { fields: createMainPurseChatPaymentFields(review.value) }; case 'ResourceAllocation': return { fields: createResourceAllocationFields(review.value) }; } @@ -291,6 +298,68 @@ function createRequestingProductFields(review: IdentityDisclosureReview | Produc return [{ label: 'Requesting product', value: review.productId }]; } +function createChatAuthorityFields(review: ChatAuthorityReview): ConfirmationField[] { + return [ + { label: 'Requesting product', value: review.productId }, + { + label: 'Permission', + value: 'Bind its device account to your wallet Chat identity and encrypt or decrypt Chat routing data', + }, + ]; +} + +function createMainPurseChatPaymentFields(review: MainPurseChatPaymentReview): ConfirmationField[] { + const services = getActiveServicesConfig(); + if ( + services.coinage === undefined || + review.coinageInstanceId !== services.coinage.instanceId || + formatBytes(review.genesisHash) !== services.people.genesis.toLowerCase() + ) { + throw new Error('Main-purse payment does not match the configured chain and asset'); + } + // Keep u64 amounts exact through the review; Number loses cents above 2^53. + const symbol = services.coinage.symbol; + const amount = (cents: bigint): string => + `${(cents / 100n).toString()}.${(cents % 100n).toString().padStart(2, '0')} ${symbol}`; + return [ + { label: 'Requesting product', value: review.callingProductId }, + { + label: 'Recipient', + value: review.recipientUsername ?? 'Unnamed identity', + }, + { + label: 'Recipient identity', + value: formatBytes(review.recipientIdentity), + mono: true, + }, + { label: 'Recipient amount', value: amount(review.amountCents) }, + { + label: 'Maximum purse debit (including fees)', + value: amount(review.maxDebitCents), + }, + { + label: 'Chain genesis', + value: formatBytes(review.genesisHash), + mono: true, + }, + { + label: 'Coinage asset instance', + value: String(review.coinageInstanceId), + }, + { + label: 'Payment operation', + value: formatBytes(review.operationId), + mono: true, + }, + { + label: 'One-time payment', + value: + 'Spend from your main purse for this payment only. Chat access and automatic signing never approve payments.', + warning: true, + }, + ]; +} + function formatResource(resource: AllocatableResource): string { return resource.tag === 'SmartContractAllowance' ? `SmartContractAllowance / ${formatDerivationIndex(resource.value)}` @@ -345,6 +414,18 @@ function confirmationCopy(review: ModalReview): ConfirmationCopy { action: 'Allow', cancelAction: 'Deny', }; + case 'ChatAuthority': + return { + title: 'Chat Identity Authority', + action: 'Allow', + cancelAction: 'Deny', + }; + case 'MainPurseChatPayment': + return { + title: 'Send Main-Purse Payment', + action: 'Send payment', + cancelAction: 'Reject', + }; case 'ProductSubtree': return { title: 'Product Account', diff --git a/packages/ui/src/host-callbacks/handlers.ts b/packages/ui/src/host-callbacks/handlers.ts index 078fc3d5e..3af5fa4bf 100644 --- a/packages/ui/src/host-callbacks/handlers.ts +++ b/packages/ui/src/host-callbacks/handlers.ts @@ -7,7 +7,7 @@ // storage keys, and sign modal titles. // - product storage keys are opaque; Rust core owns product namespacing. // -import { localizeTimestamps, type RequiredHostCallbacks } from '@parity/truapi-host'; +import { localizeTimestamps, type ContactsPlatform, type RequiredHostCallbacks } from '@parity/truapi-host'; import { createNavigateTo } from './OpenUrl.js'; import { createNotificationAdapters } from './PushNotification.js'; import { createPromptPermission } from './PromptPermission.js'; @@ -19,7 +19,7 @@ import { } from './LocalStorage.js'; import { createProductOperations } from './ProductOperations.js'; import { createPreimageAdapters } from './Preimage.js'; -import { createChainConnect } from './Chain.js'; +import { createChainConnect, createHopProvider } from './Chain.js'; import { createFeatureSupported } from './FeatureSupported.js'; import { createSupportedChains } from './SupportedChains.js'; import { createThemeSubscribe } from './Theme.js'; @@ -36,6 +36,8 @@ export interface CreateHostCallbacksOptions { pairingDotSuffix?: boolean | undefined; pairingHostGlobal?: boolean | undefined; blockingModalScope?: BlockingModalScope; + custodyLease?: string; + contacts?: Required; } export function createHostCallbacks(options: CreateHostCallbacksOptions): RequiredHostCallbacks { @@ -45,6 +47,8 @@ export function createHostCallbacks(options: CreateHostCallbacksOptions): Requir pairingDotSuffix, pairingHostGlobal, blockingModalScope = createBlockingModalScope(), + custodyLease, + contacts, } = options; return { navigation: { navigateTo: createNavigateTo() }, @@ -61,7 +65,7 @@ export function createHostCallbacks(options: CreateHostCallbacksOptions): Requir subscribeStorage: createLocalStorageSubscribe(), }, productOperations: createProductOperations(), - coreStorage: createSessionStoreAdapters(), + coreStorage: createSessionStoreAdapters(custodyLease), auth: { authStateChanged: createAuthStateChanged(pairingLabel ?? label, { dotSuffix: pairingDotSuffix, @@ -73,8 +77,10 @@ export function createHostCallbacks(options: CreateHostCallbacksOptions): Requir locale: { subscribeLocale: createLocaleSubscribe(), localizeTimestamps }, preimage: createPreimageAdapters(label), chain: { connect: createChainConnect() }, + hop: createHopProvider(), // Always served; the core itself denies chat calls on non-Chat // executions and without an active session. chat: createChatPlatform(), + ...(contacts === undefined ? {} : { contacts }), }; } diff --git a/packages/ui/src/page-core.ts b/packages/ui/src/page-core.ts index f313a61a7..0c50f289a 100644 --- a/packages/ui/src/page-core.ts +++ b/packages/ui/src/page-core.ts @@ -6,7 +6,12 @@ // also retains the page core while no product is visible. import { DEBUG, getActiveServicesConfig } from '@dotli/config'; -import { requestWalletOwner, subscribeWalletOwnerRevoked, WALLET_OWNER_REVOKED_EVENT } from '@dotli/protocol'; +import { + requestCoreCustody, + requestWalletOwner, + subscribeWalletOwnerRevoked, + WALLET_OWNER_REVOKED_EVENT, +} from '@dotli/protocol'; import { log } from '@dotli/shared'; import type { AuthState, @@ -14,12 +19,22 @@ import type { RequiredHostCallbacks, TrUApiProductProvider, } from '@parity/truapi-host'; -import type { LocalIdentity, WorkerPairingHostRuntime, WorkerSigningHostRuntime } from '@parity/truapi-host/web'; -import { createWebWorkerPairingHostRuntime, createWebWorkerSigningHostRuntime } from '@parity/truapi-host/web'; +import type { + BrowserNativeChatFilesHost, + LocalIdentity, + WorkerPairingHostRuntime, + WorkerSigningHostRuntime, +} from '@parity/truapi-host/web'; +import { + createBrowserNativeChatFilesHost, + createWebWorkerPairingHostRuntime, + createWebWorkerSigningHostRuntime, +} from '@parity/truapi-host/web'; import HostWorker from '@parity/truapi-host/worker-runtime?worker'; import type { BlockingModalCoordinator } from './blocking-modal-queue.js'; import { createHostCallbacks } from './host-callbacks/handlers.js'; import { dispatchAuthState } from './host-callbacks/AuthState.js'; +import { createContactsPlatform, NativeChatContactsDirectory } from './host-callbacks/Contacts.js'; import { initializeLocalWalletState, isExperimentalWalletActive, @@ -88,6 +103,7 @@ const cores = new Set(); let generation = 0; let walletOwnerLease: Promise | undefined; let ownerRevocationBound = false; +let custodyOperations: Promise = Promise.resolve(); let localIdentityUpdateQueue: Promise = Promise.resolve(); const noop = (): void => undefined; @@ -128,6 +144,8 @@ export function disposePageCores(): void { } } +window.addEventListener('pagehide', disposePageCores); + async function ensureWalletOwner(): Promise { if (!ownerRevocationBound) { ownerRevocationBound = true; @@ -236,6 +254,7 @@ function createCore(product: PageProduct): Core { const coordinator = modalCoordinator; const blockingModalScope = coordinator.createScope(); const connectionDisposers = new Set<() => void>(); + let runtimeCallbacks: RequiredHostCallbacks | undefined; const context = isExperimentalWalletActive() ? localWalletContext() : undefined; const { productId: _productId, ...hostConfig } = createTruapiRuntimeConfig(product.label, product.productId); let booted: PageRuntime | undefined; @@ -249,55 +268,122 @@ function createCore(product: PageProduct): Core { let nativeSessionUiInfo: LiveLocalWallet['nativeSessionUiInfo']; let walletAuthReady = false; let pendingWalletAuthState: AuthState | undefined; + let custodyLease: string | undefined; + let nativeChatFiles: BrowserNativeChatFilesHost | undefined; + const contactsGenesis = getActiveServicesConfig().people.genesis; + const contactsDirectory = + context === undefined + ? undefined + : new NativeChatContactsDirectory( + () => + !disposed && isCurrentLocalWallet(context) && contactsGenesis === getActiveServicesConfig().people.genesis, + ); + const nativeContacts = + contactsDirectory === undefined ? undefined : createContactsPlatform(contactsDirectory, blockingModalScope); + const releaseCustody = (): void => { + // Queue after an in-flight acquisition. A replacement core cannot acquire + // until this terminated signer has released even a late-arriving lease. + custodyOperations = custodyOperations + .then(async () => { + if (custodyLease === undefined) { + return; + } + const lease = custodyLease; + custodyLease = undefined; + await requestCoreCustody({ action: 'release', lease }); + }) + .catch(noop); + }; const assertCurrent = (): void => { if (disposed || (context === undefined ? isExperimentalWalletActive() : !isCurrentLocalWallet(context))) { throw new Error('Wallet or network changed while the page core was starting.'); } }; - const callbacks = createHostCallbacks({ - label: product.label, - pairingLabel: product.pairing?.label, - pairingDotSuffix: product.pairing?.dotSuffix, - pairingHostGlobal: product.pairing?.hostGlobal, - blockingModalScope, - }); - const forwardAuthState = callbacks.auth.authStateChanged; - callbacks.auth.authStateChanged = state => { - if (disposed || (context === undefined ? isExperimentalWalletActive() : !isCurrentLocalWallet(context))) { - return; + const runtime = Promise.resolve().then(async (): Promise => { + assertCurrent(); + if (context !== undefined) { + await ensureWalletOwner(); + assertCurrent(); + const acquisition = custodyOperations.then(async () => { + assertCurrent(); + const acquired = await requestCoreCustody({ action: 'acquire', walletRevision: context.revision }); + if (typeof acquired !== 'string') { + throw new Error('Private wallet custody was not acquired'); + } + custodyLease = acquired; + assertCurrent(); + }); + custodyOperations = acquisition.catch(noop); + await acquisition; } - if (context === undefined) { - forwardAuthState(state); - return; + const callbacks = createHostCallbacks({ + label: product.label, + pairingLabel: product.pairing?.label, + pairingDotSuffix: product.pairing?.dotSuffix, + pairingHostGlobal: product.pairing?.hostGlobal, + blockingModalScope, + ...(custodyLease === undefined ? {} : { custodyLease }), + ...(nativeContacts === undefined ? {} : { contacts: nativeContacts.callbacks }), + }); + runtimeCallbacks = callbacks; + if (contactsDirectory !== undefined) { + callbacks.coreStorage = contactsDirectory.observeStorage(callbacks.coreStorage); + } + if (custodyLease !== undefined) { + const lease = custodyLease; + nativeChatFiles = createBrowserNativeChatFilesHost({ + async putSources(sources) { + await requestCoreCustody({ action: 'putSources', lease, sources: [...sources] }); + }, + async readSource(sourceId) { + const blob = await requestCoreCustody({ action: 'readSource', lease, sourceId }); + if (blob !== undefined && !(blob instanceof Blob)) { + throw new Error('Invalid private Chat source'); + } + return blob; + }, + async releaseSource(sourceId) { + await requestCoreCustody({ action: 'releaseSource', lease, sourceId }); + }, + }); + callbacks.nativeChatFiles = nativeChatFiles; } - if (state.tag === 'Connected') { - const account = state.value.identityAccountId; - if (account === undefined || !/^(?:0x)?[0-9a-fA-F]{64}$/.test(account)) { + const forwardAuthState = callbacks.auth.authStateChanged; + callbacks.auth.authStateChanged = state => { + if (disposed || (context === undefined ? isExperimentalWalletActive() : !isCurrentLocalWallet(context))) { return; } - const identityAccountId = `0x${account.replace(/^0x/, '').toLowerCase()}`; - if (core.wallet !== undefined && identityAccountId !== core.wallet.binding.identityAccountId) { + contactsDirectory?.invalidate(); + if (context === undefined) { + forwardAuthState(state); return; } - const liteUsername = state.value.liteUsername; - activatedIdentity = { - identityAccountId, - ...(liteUsername !== undefined && liteUsername !== '' ? { liteUsername } : {}), - }; - nativeSessionUiInfo = { publicKey: state.value.publicKey, fullUsername: state.value.fullUsername }; - if (core.wallet !== undefined) { - core.wallet.identity = activatedIdentity; - core.wallet.nativeSessionUiInfo = nativeSessionUiInfo; + if (state.tag === 'Connected') { + const account = state.value.identityAccountId; + if (account === undefined || !/^(?:0x)?[0-9a-fA-F]{64}$/.test(account)) { + return; + } + const identityAccountId = `0x${account.replace(/^0x/, '').toLowerCase()}`; + if (core.wallet !== undefined && identityAccountId !== core.wallet.binding.identityAccountId) { + return; + } + const liteUsername = state.value.liteUsername; + activatedIdentity = { + identityAccountId, + ...(liteUsername !== undefined && liteUsername !== '' ? { liteUsername } : {}), + }; + nativeSessionUiInfo = { publicKey: state.value.publicKey, fullUsername: state.value.fullUsername }; + if (core.wallet !== undefined) { + core.wallet.identity = activatedIdentity; + core.wallet.nativeSessionUiInfo = nativeSessionUiInfo; + } } - } - if (walletAuthReady) { - forwardAuthState(state); - } else { - pendingWalletAuthState = state; - } - }; - const runtime = Promise.resolve().then(async (): Promise => { - assertCurrent(); + if (walletAuthReady) { + forwardAuthState(state); + } else { + pendingWalletAuthState = state; + } + }; if (context === undefined) { worker = new HostWorker(); booted = await createWebWorkerPairingHostRuntime(worker, callbacks, { hostConfig }); @@ -313,17 +399,19 @@ function createCore(product: PageProduct): Core { }); return pairing; } - await ensureWalletOwner(); - assertCurrent(); const secret = await readLocalWalletSecret(); if (secret === undefined) { throw new Error('Experimental wallet is unavailable. Disconnect it in the debug bar.'); } try { assertCurrent(); + const { dotns, coinage } = getActiveServicesConfig(); worker = new HostWorker(); const signing = await createWebWorkerSigningHostRuntime(worker, callbacks, { - hostConfig: { ...hostConfig, networkSuffix: getActiveServicesConfig().dotns.TLD }, + hostConfig: + coinage === undefined + ? { ...hostConfig, networkSuffix: dotns.TLD } + : { ...hostConfig, networkSuffix: dotns.TLD, coinageInstanceId: coinage.instanceId }, }); booted = signing; assertCurrent(); @@ -332,6 +420,10 @@ function createCore(product: PageProduct): Core { if (activatedIdentity === undefined) { throw new Error('Native activation did not report its identity.'); } + if (nativeSessionUiInfo?.publicKey === undefined || contactsDirectory === undefined) { + throw new Error('Native Chat contacts require the activated signing wallet'); + } + contactsDirectory.bind(signing, nativeSessionUiInfo.publicKey, contactsGenesis); const binding: LocalWalletIdentityBinding = { ...context, identityAccountId: activatedIdentity.identityAccountId, @@ -429,35 +521,43 @@ function createCore(product: PageProduct): Core { persistent: context !== undefined, faulted: false, openCallbacks() { - if (disposed) { + if (disposed || runtimeCallbacks === undefined) { throw new Error('Page core callbacks are unavailable'); } const scope = coordinator.createScope(); - const connectionCallbacks = createHostCallbacks({ + const contacts = contactsDirectory === undefined ? undefined : createContactsPlatform(contactsDirectory, scope); + const callbacks = createHostCallbacks({ label: product.label, blockingModalScope: scope, + ...(custodyLease === undefined ? {} : { custodyLease }), + ...(contacts === undefined ? {} : { contacts: contacts.callbacks }), }); - // Authentication and session storage stay core-owned; interactive - // product prompts cannot outlive the connection that requested them. + // Session state, encrypted storage and file custody belong to the core. + // Interactive product prompts belong only to their live connection. let closed = false; - connectionCallbacks.auth = { + const auth = runtimeCallbacks.auth; + callbacks.auth = { authStateChanged: state => { if (!closed) { - callbacks.auth.authStateChanged(state); + auth.authStateChanged(state); } }, }; - connectionCallbacks.coreStorage = callbacks.coreStorage; + callbacks.coreStorage = runtimeCallbacks.coreStorage; + if (nativeChatFiles !== undefined) { + callbacks.nativeChatFiles = nativeChatFiles; + } const dispose = (): void => { if (closed) { return; } closed = true; connectionDisposers.delete(dispose); + contacts?.dispose(); scope.dispose(); }; connectionDisposers.add(dispose); - return { callbacks: connectionCallbacks, dispose }; + return { callbacks, dispose }; }, dispose() { if (disposed) { @@ -474,6 +574,8 @@ function createCore(product: PageProduct): Core { for (const dispose of connectionDisposers) { dispose(); } + nativeContacts?.dispose(); + contactsDirectory?.dispose(); blockingModalScope.dispose(); monitor?.dispose(); booted?.dispose(); @@ -482,6 +584,8 @@ function createCore(product: PageProduct): Core { if (context !== undefined) { worker?.terminate(); } + nativeChatFiles?.dispose(); + releaseCustody(); }, }; cores.add(core); diff --git a/packages/ui/src/permission-modal.ts b/packages/ui/src/permission-modal.ts index 2cef70929..9a48b40f5 100644 --- a/packages/ui/src/permission-modal.ts +++ b/packages/ui/src/permission-modal.ts @@ -11,7 +11,7 @@ import type { ModalButton } from './state/modals.js'; // Shows a confirmation dialog when a product requests a permission the // host can actually gate: the Permissions-Policy-backed device // variants (Camera, Microphone, Location, Bluetooth, NFC, Clipboard, -// Biometrics, Notifications), identity disclosure, +// Biometrics, Notifications), Chat identity authority, identity disclosure, // and the internal submitted gates (ChainSubmit, PreimageSubmit, // StatementSubmit). `OpenUrl` is auto-granted at the container level and never // reaches this modal. @@ -30,6 +30,7 @@ export const PERMISSION_DESCRIPTIONS: Record NFC: 'Read and write nearby NFC tags', Clipboard: 'Read text and data from your clipboard', 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', ChainSubmit: 'Sign and submit on-chain transactions on your behalf', PreimageSubmit: 'Store preimage data on-chain via the Bulletin network', @@ -72,6 +73,11 @@ const PERMISSION_ICONS: Record = { '' + '' + '', + ChatAuthority: + '' + + '' + + '' + + '', IdentityDisclosure: '' + '' + diff --git a/packages/ui/src/permissions.ts b/packages/ui/src/permissions.ts index 8f2dccef5..cfd8c0b76 100644 --- a/packages/ui/src/permissions.ts +++ b/packages/ui/src/permissions.ts @@ -22,7 +22,7 @@ import type { export type DevicePermissionName = HostDevicePermissionRequest; export type PermissionName = - DevicePermissionName | 'ChainSubmit' | 'IdentityDisclosure' | 'PreimageSubmit' | 'StatementSubmit'; + DevicePermissionName | 'ChainSubmit' | 'ChatAuthority' | 'IdentityDisclosure' | 'PreimageSubmit' | 'StatementSubmit'; /** Device permissions the host can't actually gate (see AUTO_GRANT_DEVICE_PERMISSIONS). */ export type AutoGrantDevicePermission = 'OpenUrl'; @@ -90,6 +90,7 @@ export const ALL_PERMISSIONS: readonly { { name: 'NFC', label: 'NFC' }, { name: 'Clipboard', label: 'Clipboard' }, { name: 'Biometrics', label: 'Biometrics' }, + { name: 'ChatAuthority', label: 'Chat Identity Authority' }, { name: 'IdentityDisclosure', label: 'Identity Disclosure' }, { name: 'ChainSubmit', label: 'Sign Transactions' }, { name: 'PreimageSubmit', label: 'Submit Preimages' }, @@ -141,6 +142,9 @@ export function authorizationRequest(permission: PermissionName): PermissionAuth value: { permission: { tag: permission } }, }; } + if (permission === 'ChatAuthority') { + return { tag: 'ChatAuthority' }; + } if (permission === 'IdentityDisclosure') { return { tag: 'IdentityDisclosure' }; } @@ -193,7 +197,7 @@ export async function setPermissionStatus( ): Promise { const provider = providerFor(label); if (provider === null) { - return; + throw new Error('product connection is unavailable'); } await provider.setPermissionAuthorizationStatus(authorizationRequest(permission), toAuthorizationStatus(status)); } diff --git a/packages/ui/src/runtime-config.ts b/packages/ui/src/runtime-config.ts index fc59489ba..8d4e15b19 100644 --- a/packages/ui/src/runtime-config.ts +++ b/packages/ui/src/runtime-config.ts @@ -30,6 +30,7 @@ export function createTruapiRuntimeConfig( productId, host: { name: 'Polkadot Web', + platform: 'Web', ...(typeof __DOTLI_VERSION__ === 'string' ? { version: __DOTLI_VERSION__ } : {}), }, platform: { diff --git a/packages/ui/src/state/modals.ts b/packages/ui/src/state/modals.ts index 7dc571d77..1adcced59 100644 --- a/packages/ui/src/state/modals.ts +++ b/packages/ui/src/state/modals.ts @@ -23,6 +23,11 @@ export interface ModalButton { result: R; } +export interface ModalChoice { + label: string; + result: R; +} + export interface ModalPasswordInput { kind: 'password'; placeholder: string; @@ -37,6 +42,8 @@ export interface ModalView { fields: ModalField[]; notice?: string; input?: ModalPasswordInput; + /** Host-owned choices, rendered separately from the action footer. */ + choices?: ModalChoice[]; /** Display order. */ buttons: ModalButton[]; dismissOnBackdrop: boolean; diff --git a/packages/ui/src/styles/signing.css b/packages/ui/src/styles/signing.css index 4e34c2a3b..cc36b5510 100644 --- a/packages/ui/src/styles/signing.css +++ b/packages/ui/src/styles/signing.css @@ -155,3 +155,17 @@ opacity: 0.5; cursor: not-allowed; } + +.contacts-picker-list { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 20px; +} +.contacts-picker-choice { + display: flex; + flex-direction: column; + gap: 6px; + text-align: left; + overflow-wrap: anywhere; +} diff --git a/packages/ui/tests/blocking-modal-queue.test.ts b/packages/ui/tests/blocking-modal-queue.test.ts index 11beb36f2..be5ea1449 100644 --- a/packages/ui/tests/blocking-modal-queue.test.ts +++ b/packages/ui/tests/blocking-modal-queue.test.ts @@ -1,4 +1,4 @@ -import { afterEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, describe, expect, it, onTestFinished, vi } from 'vitest'; import type { ProductContext } from '@parity/truapi-host'; import { createBlockingModalCoordinator } from '../src/blocking-modal-queue.js'; import { createUserConfirmationAdapters } from '../src/host-callbacks/UserConfirmation.js'; @@ -20,6 +20,17 @@ afterEach(() => { describe('blocking modal queue', () => { it('As a dotli integrator, the host serializes user confirmation and device permission prompts', async () => { // Given + let status: 'NotDetermined' | 'Denied' | 'Authorized' = 'NotDetermined'; + const unregister = registerPermissionAuthorizationProvider('localhost:3000', { + getPermissionAuthorizationStatuses(requests) { + return Promise.resolve(requests.map(() => status)); + }, + setPermissionAuthorizationStatus(_request, next) { + status = next; + return Promise.resolve(); + }, + }); + onTestFinished(unregister); const scope = createBlockingModalCoordinator().createScope(); const callbacks = createHostCallbacks({ label: 'localhost:3000', diff --git a/packages/ui/tests/bridge-wallet.test.ts b/packages/ui/tests/bridge-wallet.test.ts index 719f3372d..9306ce0b7 100644 --- a/packages/ui/tests/bridge-wallet.test.ts +++ b/packages/ui/tests/bridge-wallet.test.ts @@ -42,6 +42,9 @@ const wallet = vi.hoisted(() => { const owner = vi.hoisted(() => ({ requests: [] as { action: string; lease?: string }[], revoked: new Set<(lease: string) => void>(), + custody: undefined as string | undefined, + custodyGate: undefined as Promise | undefined, + custodyStarted: false, })); vi.mock('@dotli/config', async original => ({ @@ -54,6 +57,21 @@ vi.mock('../../shared/src/chat-capability.js', () => ({ vi.mock('../src/notification.js', () => ({ showNotification: vi.fn() })); vi.mock('../../protocol/src/client.js', async original => ({ ...(await original>()), + requestCoreCustody: async (operation: { action: string; lease?: string }) => { + if (operation.action === 'acquire') { + owner.custodyStarted = true; + await owner.custodyGate; + if (owner.custody !== undefined) { + throw new Error('A signing runtime already owns this wallet in this page'); + } + owner.custody = crypto.randomUUID(); + return owner.custody; + } + if (operation.action === 'release' && operation.lease === owner.custody) { + owner.custody = undefined; + } + return undefined; + }, requestWalletOwner: (operation: { action: string; lease?: string }) => { owner.requests.push(operation); return Promise.resolve(operation.action === 'acquire' ? 'page-lease' : undefined); @@ -93,6 +111,7 @@ vi.mock('@parity/truapi-host/worker-runtime?worker', () => ({ }, })); vi.mock('@parity/truapi-host/web', () => ({ + createBrowserNativeChatFilesHost: () => ({ dispose: vi.fn() }), createWebWorkerPairingHostRuntime: vi.fn(), createWebWorkerSigningHostRuntime: (_worker: unknown, callbacks: RequiredHostCallbacks) => { let closeError: Error | undefined; @@ -139,6 +158,7 @@ vi.mock('@parity/truapi-host/web', () => ({ }); }; return Promise.resolve({ + notifyContactsChanged: assertLive, activateLocalSession: () => Promise.resolve().then(() => { publish(); @@ -296,6 +316,9 @@ describe('host-owned experimental identity', () => { wallet.sessions.length = 0; owner.requests.length = 0; owner.revoked.clear(); + owner.custody = undefined; + owner.custodyGate = undefined; + owner.custodyStarted = false; auth.length = 0; localStorage.clear(); localStorage.setItem('dotli:local-wallet-enabled', '1'); @@ -316,6 +339,9 @@ describe('host-owned experimental identity', () => { // Dispose the same freshly imported page core, not a static older module. const { disposePageCores } = await import('../src/page-core.js'); disposePageCores(); + await vi.waitFor(() => { + expect(owner.custody).toBeUndefined(); + }); const { resetOverlays } = await import('./helpers/overlays.js'); resetOverlays(); for (const [type, listener] of pageListeners) { @@ -325,6 +351,26 @@ describe('host-owned experimental identity', () => { vi.restoreAllMocks(); }); + it('releases late custody before a replacement core starts signing', async () => { + const { experimentalWalletControls: controls } = boot(); + const gate = Promise.withResolvers(); + owner.custodyGate = gate.promise; + const first = controls.getIdentity(); + const rejected = expect(first).rejects.toThrow('Wallet or network changed'); + await vi.waitFor(() => { + expect(owner.custodyStarted).toBe(true); + }); + // Use this test's reset module instance, not a statically retained core. + const { disposePageCores } = await import('../src/page-core.js'); + disposePageCores(); + const replacement = controls.getIdentity(); + gate.resolve(undefined); + await rejected; + await expect(replacement).resolves.toMatchObject({ identityAccountId: wallet.account }); + expect(wallet.sessions).toHaveLength(1); + expect(nth(wallet.sessions, 0).disposed).toBe(false); + }); + it('queries and claims identity before a product exists', async () => { const { experimentalWalletControls: controls } = boot(); await expect(controls.getIdentity()).resolves.toMatchObject({ diff --git a/packages/ui/tests/bridge.test.ts b/packages/ui/tests/bridge.test.ts index a5d103d69..cc81fff95 100644 --- a/packages/ui/tests/bridge.test.ts +++ b/packages/ui/tests/bridge.test.ts @@ -101,6 +101,7 @@ vi.mock('@parity/truapi-host', async importOriginal => ({ })); vi.mock('@parity/truapi-host/web', () => ({ + createBrowserNativeChatFilesHost: vi.fn(), createWebWorkerPairingHostRuntime: mocks.createWebWorkerPairingHostRuntime, createWebWorkerSigningHostRuntime: mocks.createWebWorkerSigningHostRuntime, createIframeHost: mocks.createIframeHost, diff --git a/packages/ui/tests/components/shell/permissions-popover.test.tsx b/packages/ui/tests/components/shell/permissions-popover.test.tsx index 1fdd13a8c..a11a4247d 100644 --- a/packages/ui/tests/components/shell/permissions-popover.test.tsx +++ b/packages/ui/tests/components/shell/permissions-popover.test.tsx @@ -40,6 +40,8 @@ function nameOf(request: PermissionAuthorizationRequest): string { return request.value.permission.tag; case 'IdentityDisclosure': case 'AccountAccess': + case 'ChatAuthority': + case 'StatementStoreAllowance': return request.tag; } } diff --git a/packages/ui/tests/contacts.test.ts b/packages/ui/tests/contacts.test.ts new file mode 100644 index 000000000..ef1ce9468 --- /dev/null +++ b/packages/ui/tests/contacts.test.ts @@ -0,0 +1,284 @@ +import type { ContactsPlatform, CoreStorage, NativeChatContactsSnapshot, 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 { must } from './support.js'; + +const walletPublicKey = `0x${'11'.repeat(32)}` as const; +const genesisHash = `0x${'55'.repeat(32)}` as const; +const alice = `0x${'22'.repeat(32)}` as const; +const bob = `0x${'33'.repeat(32)}` as const; +const handleKey = `0x${'44'.repeat(32)}` as const; +// Independently calculated with Python hashlib.blake2b(key=..., digest_size=32). +const aliceHandle = '0xa8c0dc7c8c1e82224a2c7be7fd3b8d79e29269c9dd39e644f06baaeef89c3dfb'; +const bobHandle = '0xfc326af887cd38c6306da9ee43cc7499eea214bdb364b3545550fa332fecfa87'; +const product: ProductContext = { + productId: 'chat-client.paseo', + executionKind: 'App', +}; +const cleanups: (() => void)[] = []; + +afterEach(() => { + for (const cleanup of cleanups.splice(0)) { + cleanup(); + } + resetOverlays(); + document.body.replaceChildren(); +}); + +function fixture(): { + directory: NativeChatContactsDirectory; + adapter: { callbacks: Required; dispose(): void }; + coordinator: BlockingModalCoordinator; + snapshot: NativeChatContactsSnapshot; + setRead(value: () => Promise): void; + switchSession(): void; +} { + let snapshot: NativeChatContactsSnapshot = { + walletPublicKey, + genesisHash, + contacts: [{ peerIdentity: alice, username: 'alice.paseo' }, { peerIdentity: bob }], + }; + let current = true; + let read: () => Promise = () => Promise.resolve(snapshot); + const directory = new NativeChatContactsDirectory(() => current); + directory.bind( + { + getNativeChatContacts: () => read(), + notifyContactsChanged: () => undefined, + }, + walletPublicKey, + genesisHash, + ); + const coordinator = createBlockingModalCoordinator(); + const scope = coordinator.createScope(); + const adapter = createContactsPlatform(directory, scope); + cleanups.push(() => { + adapter.dispose(); + directory.dispose(); + scope.dispose(); + }); + return { + directory, + adapter, + coordinator, + get snapshot() { + return snapshot; + }, + set snapshot(value: NativeChatContactsSnapshot) { + snapshot = value; + }, + setRead(value: () => Promise) { + read = value; + }, + switchSession() { + current = false; + directory.invalidate(); + }, + }; +} + +async function choices(): Promise { + await overlaysReady(); + await expect.poll(() => document.querySelector('.contacts-picker-choice')).not.toBeNull(); + return Array.from(document.querySelectorAll('.contacts-picker-choice')); +} + +describe('native Chat contacts', () => { + it("matches keyed handles in request order without accepting another session's key", async () => { + const { adapter } = fixture(); + const unknown = `0x${'66'.repeat(32)}` as const; + await expect( + adapter.callbacks.contacts({ + handleKey, + handles: [bobHandle, unknown, aliceHandle, bobHandle], + }), + ).resolves.toEqual({ accounts: [bob, undefined, alice, bob] }); + await expect( + adapter.callbacks.contacts({ + handleKey: walletPublicKey, + handles: [aliceHandle], + }), + ).resolves.toEqual({ accounts: [undefined] }); + }); + + it('rejects malformed lookup keys and handles', async () => { + const { adapter } = fixture(); + await expect(adapter.callbacks.contacts({ handleKey: '0x00', handles: [] })).rejects.toThrow(); + await expect( + adapter.callbacks.contacts({ + handleKey, + handles: [`0x${aliceHandle.slice(2).toUpperCase()}`], + }), + ).rejects.toThrow(); + await expect(adapter.callbacks.contacts({ handleKey, handles: [] })).resolves.toEqual({ accounts: [] }); + }); + + it('renders verified names as text without exposing account IDs and revalidates the choice', async () => { + const state = fixture(); + must(state.snapshot.contacts[0], 'Alice contact').username = ''; + const picked = state.adapter.callbacks.pickContact(product); + const buttons = await choices(); + expect(must(buttons[0], 'Alice choice').textContent).toContain(''); + expect(must(buttons[0], 'Alice choice').querySelector('img')).toBeNull(); + expect(document.querySelector('[role=dialog]')?.textContent).not.toMatch(/0x[0-9a-f]{64}/i); + expect(document.querySelector('[role=dialog]')?.textContent).toContain(product.productId); + must(buttons[1], 'Bob choice').click(); + await expect(picked).resolves.toEqual({ + tag: 'Picked', + value: { account: bob }, + }); + await overlaysReady(); + expect(document.querySelector('[role=dialog]')).toBeNull(); + }); + + it('does not return a contact removed while the picker was open', async () => { + const state = fixture(); + const picked = state.adapter.callbacks.pickContact(product); + const buttons = await choices(); + state.snapshot = { ...state.snapshot, contacts: [{ peerIdentity: bob }] }; + must(buttons[0], 'Removed Alice choice').click(); + await expect(picked).rejects.toThrow(); + await expect(state.adapter.callbacks.contacts({ handleKey, handles: [aliceHandle] })).resolves.toEqual({ + accounts: [undefined], + }); + }); + + it.each(['walletPublicKey', 'genesisHash'] as const)('refuses a snapshot for a different %s', async field => { + const state = fixture(); + state.snapshot = { ...state.snapshot, [field]: `0x${'77'.repeat(32)}` }; + await expect(state.adapter.callbacks.pickContact(product)).rejects.toThrow(); + await expect(state.adapter.callbacks.contacts({ handleKey, handles: [aliceHandle] })).rejects.toThrow(); + expect(document.querySelector('[role=dialog]')).toBeNull(); + }); + + it('distinguishes an authenticated empty roster from an unavailable signing session', async () => { + const state = fixture(); + state.snapshot = { ...state.snapshot, contacts: [] }; + await expect(state.adapter.callbacks.pickContact(product)).resolves.toEqual({ tag: 'NoContacts' }); + state.setRead(() => Promise.reject(new Error('No signed-in session'))); + await expect(state.adapter.callbacks.pickContact(product)).rejects.toThrow(); + }); + + it('cancels an outstanding lookup immediately on signout and never accepts its late snapshot', async () => { + const state = fixture(); + const pending = Promise.withResolvers(); + state.setRead(() => pending.promise); + const lookup = state.adapter.callbacks.contacts({ + handleKey, + handles: [aliceHandle], + }); + const rejected = expect(lookup).rejects.toMatchObject({ + name: 'AbortError', + }); + state.switchSession(); + await rejected; + pending.resolve(state.snapshot); + await expect(state.adapter.callbacks.pickContact(product)).rejects.toMatchObject({ name: 'AbortError' }); + }); + + it("cancels an open picker when its provider closes without closing another provider's directory", async () => { + const state = fixture(); + const picked = state.adapter.callbacks.pickContact(product); + await choices(); + const rejected = expect(picked).rejects.toMatchObject({ + name: 'AbortError', + }); + state.adapter.dispose(); + await rejected; + await overlaysReady(); + expect(document.querySelector('[role=dialog]')).toBeNull(); + const other = createContactsPlatform(state.directory, state.coordinator.createScope()); + cleanups.push(() => { + other.dispose(); + }); + await expect(other.callbacks.contacts({ handleKey, handles: [aliceHandle] })).resolves.toEqual({ + accounts: [alice], + }); + }); + + it('never opens a queued picker under a replacement wallet', async () => { + const state = fixture(); + const blocker = Promise.withResolvers(); + const blockerScope = state.coordinator.createScope(); + const blocking = blockerScope.enqueue(() => blocker.promise); + const picked = state.adapter.callbacks.pickContact(product); + const rejected = expect(picked).rejects.toMatchObject({ + name: 'AbortError', + }); + state.switchSession(); + await rejected; + blocker.resolve(undefined); + await blocking; + expect(document.querySelector('[role=dialog]')).toBeNull(); + blockerScope.dispose(); + }); + + it('invalidates active selections and late lookups at both trusted roster-write boundaries', async () => { + const state = fixture(); + const stored = Promise.withResolvers(); + const backing: CoreStorage = { + readCoreStorage: () => Promise.resolve(undefined), + writeCoreStorage: () => stored.promise, + clearCoreStorage: () => Promise.resolve(), + }; + const storage = state.directory.observeStorage(backing); + const picked = state.adapter.callbacks.pickContact(product); + await choices(); + const rejectedPick = expect(picked).rejects.toMatchObject({ + name: 'AbortError', + }); + const writing = storage.writeCoreStorage( + { + tag: 'NativeChatDevice', + value: { + rootPublicKey: new Uint8Array(32), + genesisHash: new Uint8Array(32), + productId: 'chat.paseo', + }, + }, + new Uint8Array([1]), + ); + await rejectedPick; + await overlaysReady(); + expect(document.querySelector('[role=dialog]')).toBeNull(); + const pending = Promise.withResolvers(); + state.setRead(() => pending.promise); + const lookup = state.adapter.callbacks.contacts({ + handleKey, + handles: [aliceHandle], + }); + const rejectedLookup = expect(lookup).rejects.toMatchObject({ + name: 'AbortError', + }); + stored.resolve(undefined); + await writing; + await rejectedLookup; + pending.resolve(state.snapshot); + state.snapshot = { ...state.snapshot, contacts: [] }; + state.setRead(() => Promise.resolve(state.snapshot)); + await expect(state.adapter.callbacks.contacts({ handleKey, handles: [aliceHandle] })).resolves.toEqual({ + accounts: [undefined], + }); + }); + + it('dismisses by Escape and confines keyboard focus to the host picker', async () => { + const state = fixture(); + const picked = state.adapter.callbacks.pickContact(product); + const buttons = await choices(); + must(buttons[0], 'First contact choice').dispatchEvent( + new KeyboardEvent('keydown', { + key: 'Tab', + shiftKey: true, + bubbles: true, + cancelable: true, + }), + ); + expect(document.activeElement).toBe(document.querySelector('.signing-btn-cancel')); + must(document.activeElement, 'Focused picker action').dispatchEvent( + new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }), + ); + await expect(picked).resolves.toEqual({ tag: 'Dismissed' }); + }); +}); diff --git a/packages/ui/tests/permissions.test.ts b/packages/ui/tests/permissions.test.ts index b401347ff..b54219136 100644 --- a/packages/ui/tests/permissions.test.ts +++ b/packages/ui/tests/permissions.test.ts @@ -9,7 +9,6 @@ import { DEVICE_PERMISSION_POLICY, buildAllowAttribute, getGrantedDevicePermissions, - getPermissionStatuses, getPermissionStatus, hasAnyGrant, isDevicePermission, @@ -31,11 +30,9 @@ type Store = Map; let unregisterMyapp: (() => void) | null = null; let myappStore: Store; -let myappBatchReads = 0; beforeEach(() => { myappStore = new Map(); - myappBatchReads = 0; unregisterMyapp = registerTestProvider('myapp', myappStore); }); @@ -48,9 +45,6 @@ afterEach(() => { function registerTestProvider(label: string, store: Store): () => void { return registerPermissionAuthorizationProvider(label, { getPermissionAuthorizationStatuses(requests) { - if (label === 'myapp') { - myappBatchReads += 1; - } return Promise.resolve(requests.map(request => store.get(requestKey(request)) ?? 'NotDetermined')); }, setPermissionAuthorizationStatus(request, status) { @@ -71,6 +65,10 @@ function requestKey(request: PermissionAuthorizationRequest): string { return `Device:${request.value}`; case 'Remote': return `Remote:${request.value.permission.tag}`; + case 'ChatAuthority': + return 'ChatAuthority'; + case 'StatementStoreAllowance': + return `StatementStoreAllowance:${JSON.stringify(request.value.derivationIndex)}`; case 'IdentityDisclosure': return 'IdentityDisclosure'; case 'AccountAccess': @@ -114,42 +112,6 @@ describe('getPermissionStatus / setPermissionStatus', () => { expect(await getPermissionStatus('myapp', 'ChainSubmit')).toBe('denied'); }); - it('As a product, my permission decisions use the core authorization store', async () => { - // Given - expect(myappStore).toEqual(new Map()); - - // When - await setPermissionStatus('myapp', 'ChainSubmit', 'granted'); - await setPermissionStatus('myapp', 'Camera', 'denied'); - await setPermissionStatus('myapp', 'IdentityDisclosure', 'granted'); - - // Then - expect(myappStore).toEqual( - new Map([ - ['Remote:ChainSubmit', 'Authorized'], - ['Device:Camera', 'Denied'], - ['IdentityDisclosure', 'Authorized'], - ]), - ); - expect(await getPermissionStatus('myapp', 'ChainSubmit')).toBe('granted'); - expect(await getPermissionStatus('myapp', 'Camera')).toBe('denied'); - expect(await getPermissionStatus('myapp', 'IdentityDisclosure')).toBe('granted'); - }); - - it('As a product, my permission statuses are read in one provider call', async () => { - // Given - await setPermissionStatus('myapp', 'ChainSubmit', 'granted'); - await setPermissionStatus('myapp', 'Camera', 'denied'); - const callsBeforeRead = myappBatchReads; - - // When - const statuses = getPermissionStatuses('myapp', ['ChainSubmit', 'Camera', 'Microphone']); - - // Then - await expect(statuses).resolves.toEqual(['granted', 'denied', 'ask']); - expect(myappBatchReads - callsBeforeRead).toBe(1); - }); - it('As a product, my permission grants are isolated from other products', async () => { await setPermissionStatus('myapp', 'Camera', 'granted'); expect(await getPermissionStatus('otherapp', 'Camera')).toBe('ask'); @@ -170,6 +132,17 @@ describe('getPermissionStatus / setPermissionStatus', () => { // Then expect(await getPermissionStatus('myapp', 'Camera')).toBe('granted'); }); + + it('does not acknowledge a revocation after its provider disappears', async () => { + await setPermissionStatus('myapp', 'Camera', 'granted'); + unregisterMyapp?.(); + unregisterMyapp = null; + + await expect(setPermissionStatus('myapp', 'Camera', 'denied')).rejects.toThrow(); + + unregisterMyapp = registerTestProvider('myapp', myappStore); + expect(await getPermissionStatus('myapp', 'Camera')).toBe('granted'); + }); }); describe('resetPermission', () => { diff --git a/packages/ui/tests/rate-limit.test.ts b/packages/ui/tests/rate-limit.test.ts index 02e0bd1b4..975244d59 100644 --- a/packages/ui/tests/rate-limit.test.ts +++ b/packages/ui/tests/rate-limit.test.ts @@ -1,7 +1,8 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, onTestFinished, vi } from 'vitest'; import type { ProductContext } from '@parity/truapi-host'; import { createSubmitRateLimiter } from '../src/host-callbacks/rate-limit.js'; import { createHostCallbacks } from '../src/host-callbacks/handlers.js'; +import { registerPermissionAuthorizationProvider } from '../src/permissions.js'; const PRODUCT: ProductContext = { productId: 'myapp.paseo', @@ -108,15 +109,29 @@ describe('prompt rate limiting across host callbacks', () => { vi.useRealTimers(); }); - it('As a dotli integrator, the host rate limits permission prompts per callback surface', async () => { - // Given: a single host callback surface. No authorization provider is - // registered, so every prompt reaches the "ask" path and the limiter. - const { permissions } = createHostCallbacks({ label: 'myapp' }); + it('As a dotli integrator, the host counts permission and notification prompts against one shared budget', async () => { + // Reset the real grant between prompts to exercise one callback's shared budget. + let status: 'NotDetermined' | 'Denied' | 'Authorized' = 'NotDetermined'; + const unregister = registerPermissionAuthorizationProvider('myapp', { + getPermissionAuthorizationStatuses(requests) { + return Promise.resolve(requests.map(() => status)); + }, + setPermissionAuthorizationStatus(_request, next) { + status = next; + return Promise.resolve(); + }, + }); + onTestFinished(unregister); + const { permissions } = createHostCallbacks({ + label: 'myapp', + }); // When: camera prompts exhaust the whole window budget. for (let i = 0; i < MAX_PER_WINDOW; i += 1) { + status = 'NotDetermined'; await permissions.devicePermission(PRODUCT, 'Camera'); } + status = 'NotDetermined'; // Then: a different permission shares that budget and is rate limited // instead of showing a 21st modal. @@ -128,10 +143,22 @@ describe('prompt rate limiting across host callbacks', () => { it('As a dotli user, delivering notifications never spends the prompt budget', async () => { // Given + let status: 'NotDetermined' | 'Denied' | 'Authorized' = 'NotDetermined'; + const unregister = registerPermissionAuthorizationProvider('myapp', { + getPermissionAuthorizationStatuses(requests) { + return Promise.resolve(requests.map(() => status)); + }, + setPermissionAuthorizationStatus(_request, next) { + status = next; + return Promise.resolve(); + }, + }); + onTestFinished(unregister); const { permissions, notifications } = createHostCallbacks({ label: 'myapp', }); for (let i = 0; i < MAX_PER_WINDOW; i += 1) { + status = 'NotDetermined'; await permissions.devicePermission(PRODUCT, 'Camera'); } diff --git a/packages/ui/tests/runtime-config.test.ts b/packages/ui/tests/runtime-config.test.ts index 38471316f..98ecfd2b5 100644 --- a/packages/ui/tests/runtime-config.test.ts +++ b/packages/ui/tests/runtime-config.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, it } from 'vitest'; -import { NetworkName, getActiveServicesConfig, setNetworkOverride } from '@dotli/config'; +import { NetworkName, setNetworkOverride } from '@dotli/config'; import { createTruapiRuntimeConfig, labelToProductId } from '../src/runtime-config.js'; describe('labelToProductId', () => { @@ -29,31 +29,4 @@ describe('createTruapiRuntimeConfig', () => { 'truapi-playground.dot', ); }); - - it('As a dotli integrator, the host passes the full host runtime contract to the WASM core', () => { - expect(createTruapiRuntimeConfig('acme')).toEqual({ - productId: 'acme.paseo', - host: { - name: 'Polkadot Web', - icon: undefined, - version: undefined, - }, - platform: { - type: expect.any(String) as unknown, - version: undefined, - }, - people: { - genesisHash: getActiveServicesConfig().people.genesis, - }, - bulletin: { - genesisHash: getActiveServicesConfig().bulletin.genesis, - }, - assetHub: { - genesisHash: getActiveServicesConfig().assethub.genesis, - }, - pairing: { - deeplinkScheme: 'polkadotapp', - }, - }); - }); }); diff --git a/packages/ui/tests/session-store.test.ts b/packages/ui/tests/session-store.test.ts index e6d510c57..df25a0ec1 100644 --- a/packages/ui/tests/session-store.test.ts +++ b/packages/ui/tests/session-store.test.ts @@ -19,10 +19,11 @@ import { writeUiStateCache, } from '../src/host-callbacks/SessionStore.js'; import { createAuthStateChanged } from '../src/host-callbacks/AuthState.js'; -import type { CoreStorageKey, SessionUiInfo } from '@parity/truapi-host'; +import type { CoreStorage, CoreStorageKey, SessionUiInfo } from '@parity/truapi-host'; import { must } from './support.js'; -import type { SharedWalletOperation, SharedWalletState } from '@dotli/protocol'; +import type { CoreCustodyOperation, SharedWalletOperation, SharedWalletState } from '@dotli/protocol'; import { handleWalletOperation } from '../../../apps/protocol/src/wallet-storage.js'; +import { handleCoreCustody } from '../../../apps/protocol/src/core-custody.js'; const buildFlags = vi.hoisted(() => ({ debug: false })); vi.mock('@dotli/config', async importOriginal => ({ @@ -40,6 +41,7 @@ const sharedAuth = vi.hoisted(() => ({ })); vi.mock('../../protocol/src/client.js', () => ({ + requestCoreCustody: (operation: CoreCustodyOperation) => handleCoreCustody(operation), requestSharedWallet: async (_siteId: string, operation: SharedWalletOperation) => { if (sharedAuth.walletError !== undefined) { throw sharedAuth.walletError; @@ -104,9 +106,30 @@ const CONNECTED_DETAIL = { }; const walletLockTails = new Map>(); +let custodyLease: string | undefined; + +async function experimentalStore(factory = createSessionStoreAdapters): Promise { + if (custodyLease !== undefined) { + await handleCoreCustody({ action: 'release', lease: custodyLease }); + } + const wallet = await handleWalletOperation({ action: 'state' }, () => {}); + const acquired = await handleCoreCustody({ + action: 'acquire', + walletRevision: wallet.state.revision, + }); + if (typeof acquired !== 'string') { + throw new Error('Custody was not acquired'); + } + custodyLease = acquired; + return factory(acquired); +} describe('session-store host callbacks', () => { - beforeEach(() => { + beforeEach(async () => { + if (custodyLease !== undefined) { + await handleCoreCustody({ action: 'release', lease: custodyLease }); + custodyLease = undefined; + } buildFlags.debug = false; localStorage.clear(); sharedAuth.storage.clear(); @@ -116,8 +139,13 @@ describe('session-store host callbacks', () => { Object.defineProperty(navigator, 'locks', { configurable: true, value: { - request(name: string, callback: () => Promise): Promise { - const result = (walletLockTails.get(name) ?? Promise.resolve()).then(callback); + request( + name: string, + options: LockOptions | (() => Promise), + callback?: (lock: object | null) => Promise, + ): Promise { + const run = typeof options === 'function' ? options : () => must(callback, 'Lock callback')({}); + const result = (walletLockTails.get(name) ?? Promise.resolve()).then(run); walletLockTails.set( name, result.then( @@ -474,7 +502,7 @@ describe('session-store host callbacks', () => { await deleteLocalWalletSecret(); const { secret } = await createLocalWalletSecret(); await setLocalWalletEnabled(true); - const experimental = createSessionStoreAdapters(); + const experimental = await experimentalStore(); await experimental.writeCoreStorage(AUTH_SESSION_KEY, new Uint8Array([3])); await experimental.writeCoreStorage(grant, new Uint8Array([4])); const stopWorkers = vi.fn(); @@ -496,14 +524,13 @@ describe('session-store host callbacks', () => { const imported = await readLocalWalletSecret(); expect(imported).toEqual(new Uint8Array(16)); imported?.fill(0); - expect(await experimental.readCoreStorage(grant)).toBeUndefined(); - expect(await experimental.readCoreStorage(AUTH_SESSION_KEY)).toBeUndefined(); - const replacement = otherTab.createSessionStoreAdapters(); + await expect(experimental.readCoreStorage(grant)).rejects.toThrow(); + await expect(experimental.readCoreStorage(AUTH_SESSION_KEY)).rejects.toThrow(); + const replacement = await experimentalStore(otherTab.createSessionStoreAdapters); await replacement.writeCoreStorage(grant, new Uint8Array([6])); - // A retired worker cannot write its old grant back after replacement. - await experimental.writeCoreStorage(grant, new Uint8Array([5])); - expect(await experimental.readCoreStorage(grant)).toBeUndefined(); - await experimental.clearCoreStorage(grant); + // A retired worker cannot acknowledge a discarded write as durable. + await expect(experimental.writeCoreStorage(grant, new Uint8Array([5]))).rejects.toThrow(); + await expect(experimental.clearCoreStorage(grant)).rejects.toThrow(); expect(await replacement.readCoreStorage(grant)).toEqual(new Uint8Array([6])); expect(await mobile.readCoreStorage(grant)).toEqual(new Uint8Array([2])); expect(await mobile.readCoreStorage(AUTH_SESSION_KEY)).toEqual(new Uint8Array([1])); @@ -552,7 +579,7 @@ describe('session-store host callbacks', () => { const { secret } = await createLocalWalletSecret(); secret.fill(0); await setLocalWalletEnabled(true); - const experimental = createSessionStoreAdapters(); + const experimental = await experimentalStore(); expect(await experimental.readCoreStorage(AUTH_SESSION_KEY)).toBeUndefined(); expect(await experimental.readCoreStorage(grant)).toBeUndefined(); await experimental.writeCoreStorage(AUTH_SESSION_KEY, new Uint8Array([3])); @@ -565,11 +592,39 @@ describe('session-store host callbacks', () => { expect(await production.readCoreStorage(grant)).toEqual(new Uint8Array([2])); buildFlags.debug = true; await deleteLocalWalletSecret(); - expect(await experimental.readCoreStorage(grant)).toBeUndefined(); + await expect(experimental.readCoreStorage(grant)).rejects.toThrow(); expect(await mobile.readCoreStorage(grant)).toEqual(new Uint8Array([2])); expect(await mobile.readCoreStorage(AUTH_SESSION_KEY)).toEqual(new Uint8Array([1])); }); + it('hands native custody to one signer at a time without losing its purse on release', async () => { + buildFlags.debug = true; + const { secret } = await createLocalWalletSecret(); + secret.fill(0); + await setLocalWalletEnabled(true); + const first = await experimentalStore(); + const purse = { + tag: 'MainPurseCoinage', + value: { + rootPublicKey: new Uint8Array(32).fill(7), + genesisHash: new Uint8Array(32).fill(8), + }, + } satisfies CoreStorageKey; + await first.writeCoreStorage(purse, new Uint8Array([1, 2, 3])); + const wallet = await handleWalletOperation({ action: 'state' }, () => {}); + await expect( + handleCoreCustody({ + action: 'acquire', + walletRevision: wallet.state.revision, + }), + ).rejects.toThrow(); + await expect(createSessionStoreAdapters().writeCoreStorage(purse, new Uint8Array([9]))).rejects.toThrow(); + const replacement = await experimentalStore(); + await expect(first.writeCoreStorage(purse, new Uint8Array([9]))).rejects.toThrow(); + expect(await replacement.readCoreStorage(purse)).toEqual(new Uint8Array([1, 2, 3])); + await replacement.clearCoreStorage(purse); + }); + it('As a dotli integrator, the host never reuses a nonce across allowance key writes', async () => { // Given const storage = createSessionStoreAdapters(); diff --git a/packages/ui/tests/user-confirmation.test.ts b/packages/ui/tests/user-confirmation.test.ts index 4730cbff0..4e627b341 100644 --- a/packages/ui/tests/user-confirmation.test.ts +++ b/packages/ui/tests/user-confirmation.test.ts @@ -1,11 +1,13 @@ -import type { UserConfirmation } from '@parity/truapi-host'; -import { afterEach, describe, expect, it } from 'vitest'; +import type { UserConfirmationReview } from '@parity/truapi-host'; +import { afterEach, describe, expect, it, vi } from 'vitest'; import { createUserConfirmationAdapters } from '../src/host-callbacks/UserConfirmation.js'; import { overlaysReady, resetOverlays } from './helpers/overlays.js'; - -type UserConfirmationReview = Parameters['confirmUserAction']>[0]; +import * as network from '@dotli/config'; +import { hexToBytes } from '@parity/truapi/scale'; +import { must } from './support.js'; afterEach(() => { + vi.restoreAllMocks(); resetOverlays(); document.body.replaceChildren(); }); @@ -21,6 +23,74 @@ function modalFields(): Record { } describe('user confirmation modal', () => { + it('reviews each main-purse spend separately without rounding u64 cents', async () => { + const services = network.NETWORK_NAME_TO_SERVICES_CONFIG[network.NetworkName.PASEO]; + vi.spyOn(network, 'getActiveServicesConfig').mockReturnValue(services); + const { confirmUserAction } = createUserConfirmationAdapters('egui-chat.paseo'); + const review = { + tag: 'MainPurseChatPayment', + value: { + callingProductId: 'egui-chat.paseo', + recipientIdentity: new Uint8Array(32).fill(7), + recipientUsername: 'recipient.paseo', + amountCents: 9007199254740993n, + maxDebitCents: 9007199254740994n, + genesisHash: hexToBytes(services.people.genesis), + coinageInstanceId: 0, + operationId: new Uint8Array(32).fill(9), + }, + } satisfies UserConfirmationReview; + const first = confirmUserAction(review); + await overlaysReady(); + expect(modalFields()).toMatchObject({ + 'Requesting product': 'egui-chat.paseo', + 'Recipient identity': `0x${'07'.repeat(32)}`, + 'Recipient amount': '90071992547409.93 pUSD', + 'Maximum purse debit (including fees)': '90071992547409.94 pUSD', + 'Chain genesis': services.people.genesis, + 'Coinage asset instance': '0', + 'Payment operation': `0x${'09'.repeat(32)}`, + }); + must(document.querySelector('.signing-btn-sign'), 'Approve payment').click(); + await expect(first).resolves.toBe(true); + const second = confirmUserAction({ + ...review, + value: { ...review.value, operationId: new Uint8Array(32).fill(10) }, + }); + await overlaysReady(); + expect(document.querySelector('.signing-modal')).not.toBeNull(); + must(document.querySelector('.signing-btn-cancel'), 'Cancel payment').click(); + await expect(second).resolves.toBe(false); + }); + + it('does not offer approval for a payment on an unconfigured chain or asset', async () => { + const services = network.NETWORK_NAME_TO_SERVICES_CONFIG[network.NetworkName.PASEO]; + vi.spyOn(network, 'getActiveServicesConfig').mockReturnValue(services); + const { confirmUserAction } = createUserConfirmationAdapters('egui-chat.paseo'); + const value = { + callingProductId: 'egui-chat.paseo', + recipientIdentity: new Uint8Array(32).fill(7), + amountCents: 1n, + maxDebitCents: 1n, + genesisHash: hexToBytes(services.people.genesis), + coinageInstanceId: 0, + operationId: new Uint8Array(32).fill(9), + }; + await expect( + confirmUserAction({ + tag: 'MainPurseChatPayment', + value: { ...value, genesisHash: new Uint8Array(32) }, + }), + ).rejects.toThrow(); + await expect( + confirmUserAction({ + tag: 'MainPurseChatPayment', + value: { ...value, coinageInstanceId: 1 }, + }), + ).rejects.toThrow(); + expect(document.querySelector('.signing-modal')).toBeNull(); + }); + it('As a dotli integrator, the host shows concurrent confirmation requests one at a time', async () => { // Given const { confirmUserAction } = createUserConfirmationAdapters('localhost:3000'); diff --git a/vendor/truapi-host.lock.json b/vendor/truapi-host.lock.json index 63a04f178..c60dd01b0 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/pvm-app-runtime", - "upstreamRevision": "1385ae2b7a1ce8dc89a0487a3e777bc28dd93428", + "upstreamBranch": "feat/chat-v2-product-authority", + "upstreamRevision": "901a3e754d86d9bc64bf647f103e9ea0a18de470", + "pullRequest": "https://github.com/paritytech/trinity-user-agents/pull/709", "packages": { "vendor/truapi": { "name": "@parity/truapi", "version": "0.23.0", - "sourceArchiveSha256": "d00a6100fddd4146b8891a8406664b611c0783355edf510df100d2fc733dbcbb", - "clientSha256": "1b0ed507ab520f3dbe50e0188447eb6f5f80b0e21d134dc532d66a3a955b4bf8" + "sourceArchiveSha256": "df7b537877be29d79561bc4a3d6bf4d6edb1b1d037acbcd56a9eba336a8aa3e9", + "clientSha256": "81022e6ad71842cec42396dac1ec3ed72e39e906e3867dc57d65f1142b402b69" }, "vendor/truapi-host": { "name": "@parity/truapi-host", "version": "0.23.0", - "sourceArchiveSha256": "8f6c5244b0a1265cb08b5170fa299173e645b5396d3c37ddef4fea521c7413f6", + "sourceArchiveSha256": "67b2ea10da5d36cf07fb7c629b6231f690226c8ade1da4485e1e215f056a056a", "dependencyOverride": "@parity/truapi=file:../truapi", - "wasmSha256": "b3babf2c32a9eff5768df775cdc4177958441ca0f3657ed11255a09eece97cbd", - "testingWasmSha256": "7809b919e07ef2de2dcf72d275dfee71cc11091b606dc19939f6316c301c0137", + "wasmSha256": "90b586ec9a2ee0aea25477430f75be6b3c3911df69ae92006b3e00f5724ce4e7", + "testingWasmSha256": "1a1187ac05737c8e1098f7d0791d6ac99e080fc20c45d93a3402da30c9ae9a54", "wasmFeatures": [ "wasm-signing-host" ] } }, - "wasmUpstreamRevision": "1385ae2b7a1ce8dc89a0487a3e777bc28dd93428", - "pullRequest": "https://github.com/paritytech/trinity-user-agents/pull/540" + "wasmUpstreamRevision": "901a3e754d86d9bc64bf647f103e9ea0a18de470" } diff --git a/vendor/truapi-host/LICENSE-AGPL-3.0 b/vendor/truapi-host/LICENSE-AGPL-3.0 new file mode 100644 index 000000000..a028880c7 --- /dev/null +++ b/vendor/truapi-host/LICENSE-AGPL-3.0 @@ -0,0 +1,661 @@ +GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/vendor/truapi-host/NOTICE b/vendor/truapi-host/NOTICE new file mode 100644 index 000000000..9e88567ea --- /dev/null +++ b/vendor/truapi-host/NOTICE @@ -0,0 +1,18 @@ +The original TypeScript Host adapter is MIT-licensed; see LICENSE. +The distributed Rust signing runtime/WASM includes AGPL-3.0-only code. +It is not an MIT-only distribution. See LICENSE-AGPL-3.0. + +Coinage is a modified extraction from paritytech/brevity-dozer, +revision d504259b60b88ca42f70a8378186a714887ef19f, copyright its contributors. +Detailed provenance is in rust/crates/truapi-coinage/NOTICE in the source tree. +Native HOP protocol/crypto is adapted from brevity-chat/src/hop.rs in that +same Brevity revision, under AGPL-3.0-only, with Host-private durable custody. +Native Chat wire/crypto is included in rust/crates/truapi-chat-v2, derived from +paritytech/polkavm-app-kit useragent-chat-v2 at revision +57b236fe9e740c83d0ead3d22cc7ca5a85e4ad17, under AGPL-3.0-only, with native +attachment codec and secret-zeroization modifications included in this source. + +Corresponding Source must include the exact Host source revision, all local +modifications, the Coinage provenance/license notices and build instructions. +Source repository: https://github.com/paritytech/host-rust-core +A repository URL alone does not provide unpublished local modifications. diff --git a/vendor/truapi-host/README.md b/vendor/truapi-host/README.md index eaf1d70ad..bf128f90e 100644 --- a/vendor/truapi-host/README.md +++ b/vendor/truapi-host/README.md @@ -21,6 +21,8 @@ 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 @@ -53,6 +55,19 @@ optional bundle does not replace them. Raw Wasm consumers can use routing isolation, not per-call `AbortSignal` cancellation: hosts must still retire their connection-owned interactive UI explicitly. +Signing hosts using instance-scoped Coinage must also supply `runtimeConfig.coinageInstanceId` (or +`hostConfig.coinageInstanceId` in the worker factory) from trusted host/network configuration. It is an integer from `0` +through `4294967295`, including zero; strings, fractions and out-of-range values are rejected. Omission preserves legacy +Coinage support, but Coinage operations on an instance-scoped runtime fail closed without it. This asset instance is not +a purse derivation identifier and is never selected by guest product code. + +The optional runtime-wide `callbacks.coinageWallet` group registers an existing native main-purse service through +`nativeCoinage(request)`. Omitting the group uses Core's built-in Rust wallet; no explicit backend selector is needed. A +registered native wallet remains authoritative when unavailable, locked, or failing: none of those states enables Rust +custody. Registration is captured when the runtime is constructed and cannot be replaced by product callbacks. Malformed +native groups reject initialization. Native request/response payloads, especially outgoing memos, are Host-private; +infrastructure exceptions are sanitized at the adapter boundary. + `runtimeConfig.assetHub` is required by both configurations, pairing and signing. It is the Asset Hub genesis hash, in the same shape as `runtimeConfig.people` and `runtimeConfig.bulletin`. Product manifests are read from the dotNS contracts deployed there, so it is what makes a `trustedProducts` grant resolvable: without a usable value no manifest @@ -78,7 +93,6 @@ The optional callback receives `LocalIdentityProgress` (exported from `@parity/t elapsed-time estimates. `confirming` means the backend accepted the request, not that the username is owned yet; only the resolved promise confirms ownership. A retry does not submit another registration. Observer exceptions do not interrupt the operation, and settled or disposed requests receive no further progress. - Both methods return `LocalIdentity` (exported from `@parity/truapi-host/web`): the canonical lowercase `0x`-prefixed `identityAccountId` and an optional verified `liteUsername`. The backend must allow the worker's origin, or the host must provide an approved same-origin proxy. Secret material stays in the signing runtime. Disconnecting or replacing the @@ -309,6 +323,19 @@ 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`). +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 +ready peers, and deduplicates identities. Conflicting verified names are omitted. It is not a product or SSO API; +pairing hosts reject it. Bind the result to the active signing public key and People genesis, never to a username. +Native departures/revocations remove readiness; product-private block lists are not a separate directory source. + +Actors are indexed when opened. Historical unindexed products must be opened once on the upgraded host; private storage +has no enumeration API. Directory reads share native commit gates, and native state/session/permission changes invalidate +cached handles. A browser adapter must also cancel pending picker/lookup work when its wallet, network, provider or +directory generation changes. Provider-scoped `contacts` callbacks control that provider's UI; absent overrides inherit +the runtime-wide Contacts adapter. Keep the runtime-wide source alive for host-owned rendering until the owner closes. + ## Generated WASM artefacts The ignored bundle under `dist/wasm/web/` is built with host-owned chain access. Hosts wire their JSON-RPC provider @@ -361,6 +388,20 @@ const secondProvider = await runtime.createProvider({ `@parity/truapi-host/web` also exports `createIframeHost` for the protocol-iframe MessageChannel handshake. Host code creates one worker runtime and then opens one provider per product id. +When UI callbacks capture a product label, pass that product's typed callbacks as the second argument to +`runtime.createProvider(product, callbacks)`. The worker routes these callbacks to that execution without replacing the +shared signing authority, main purse, native Chat authority, or private core storage. Wallet callbacks always use the +runtime-wide bundle, even when a provider supplies overrides. Disposing a provider does not dispose the owner runtime. A +signing host keeps one owner alive for wallet recovery, not ordinary Chat reception, and must not run independent +signing runtimes against the same purse inventory. + +`createBrowserNativeChatFilesHost(sourceStore?)` accepts an optional `BrowserNativeChatFileSourceStore` with +`putSources`, `readSource` and `releaseSource`. Use it when core custody spans host origins: immutable file sources must +remain reachable wherever the persisted actor is restored. `putSources` must commit all supplied Blob snapshots durably +before resolving; `readSource` returns that snapshot, not a mutable filesystem reference. Picker/export consent and +bounded reads remain in the SDK. The default source store is origin-local IndexedDB with private immutable Blobs, not +application encryption at rest. An embedder owns disposal of a file host it supplies. + ## Session lifecycle The core owns the session; the host owns persistence. At boot the core restores the `AuthSession` slot on its own and diff --git a/vendor/truapi-host/dist/adapter-support.d.ts b/vendor/truapi-host/dist/adapter-support.d.ts index 07ffd5186..d557c2e4f 100644 --- a/vendor/truapi-host/dist/adapter-support.d.ts +++ b/vendor/truapi-host/dist/adapter-support.d.ts @@ -1,6 +1,6 @@ import { type GenericError, type Result } from "@parity/truapi"; -import type { ChainConnect } from "./runtime.js"; -import type { ChainProvider } from "./generated/host-callbacks.js"; +import type { ChainConnect, HopConnect } from "./runtime.js"; +import type { ChainProvider, CoinageWalletHost, HopProvider, NativeChatFilesHost } from "./generated/host-callbacks.js"; type WireResult = { success: true; value: T; @@ -23,4 +23,11 @@ export declare function driveResultStream(stream: MaybeAsyncIterable): ChainConnect; +/** A missing HOP embedding is unavailable, never a successful no-op socket. */ +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; +/** Optional SDK embeddings must fail closed, never invent successful file handles. */ +export declare const unavailableNativeChatFilesHost: Required; +export declare function hopConnectAdapter(host: Required): HopConnect; export {}; diff --git a/vendor/truapi-host/dist/adapter-support.js b/vendor/truapi-host/dist/adapter-support.js index 41e4086f7..fdb0e31cd 100644 --- a/vendor/truapi-host/dist/adapter-support.js +++ b/vendor/truapi-host/dist/adapter-support.js @@ -45,25 +45,40 @@ function toAsyncIterator(stream) { * callback streams where the Rust core owns cancellation but JS owns the * iterator and any transport cleanup behind `return()`. */ -function pumpIterator(iterator, onItem, label, onError) { +function pumpIterator(iterator, onItem, label, onError, onComplete) { let stopped = false; void (async () => { try { while (!stopped) { const next = await iterator.next(); - if (next.done) + if (stopped || next.done) return; onItem(next.value); } } catch (err) { - console.error(`[truapi host callbacks] ${label} failed:`, err); - onError?.({ reason: errorMessage(err) }); + if (!stopped) { + console.error(`[truapi host callbacks] ${label} failed`); + onError?.({ reason: errorMessage(err) }); + } + } + finally { + if (!stopped) + onComplete?.(); } })(); return () => { + if (stopped) + return; stopped = true; - void iterator.return?.(); + try { + void Promise.resolve(iterator.return?.()).catch(() => { + console.error(`[truapi host callbacks] ${label} cleanup failed`); + }); + } + catch { + console.error(`[truapi host callbacks] ${label} cleanup failed`); + } }; } /** @@ -81,18 +96,127 @@ export function driveResultStream(stream, sendItem, sendError) { * `send`/`close`. */ export function chainConnectAdapter(host) { - return async (genesisHash, onResponse) => { - const connection = await host.connect(hexToBytes(genesisHash)); - const iterator = connection.responses()[Symbol.asyncIterator](); - const stopResponses = pumpIterator(iterator, onResponse, "chain responses"); - return { - send(request) { + return async (genesisHash, onResponse, onClosed) => rpcConnectionAdapter(await host.connect(hexToBytes(genesisHash)), onResponse, onClosed); +} +/** A missing HOP embedding is unavailable, never a successful no-op socket. */ +export const unavailableHopProvider = { + async allowedHopEndpoints() { + return []; + }, + async connectHop() { + throw new Error("HOP provider is unavailable"); + }, +}; +/** Native exceptions may contain bearer material; preserve only typed failure values. */ +export function coinageWalletHostAdapter(host) { + if (host === undefined) + return undefined; + let nativeCoinage; + try { + nativeCoinage = host.nativeCoinage.bind(host); + } + catch { + throw new Error("Native Coinage wallet callback is unavailable"); + } + return { + async nativeCoinage(request) { + try { + return await nativeCoinage(request); + } + catch { + throw new Error("Native Coinage wallet operation failed"); + } + }, + }; +} +/** Optional SDK embeddings must fail closed, never invent successful file handles. */ +export const unavailableNativeChatFilesHost = { + async pickChatFiles() { + throw new Error("Native Chat files are unavailable"); + }, + async readChatFile() { + throw new Error("Native Chat files are unavailable"); + }, + async releaseChatFile() { + throw new Error("Native Chat files are unavailable"); + }, + async beginChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async writeChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async finishChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async cancelChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, +}; +export function hopConnectAdapter(host) { + return async (genesisHash, endpoint, onResponse, onClosed) => { + const genesis = hexToBytes(genesisHash); + const allowed = await host.allowedHopEndpoints(genesis); + // Check the original string, never a normalized URL against the allowlist. + if (!allowed.includes(endpoint) || + !endpoint.startsWith("wss://") || + /[\s\u0000-\u001f\u007f-\u009f#\\]/u.test(endpoint) || + endpoint.slice(6).split(/[/?]/u, 1)[0].includes("@")) { + throw new Error("HOP endpoint is not an allowed secure WebSocket URL"); + } + const url = new URL(endpoint); + if (!url.hostname || url.username || url.password || url.hash) { + throw new Error("HOP endpoint is not an allowed secure WebSocket URL"); + } + return rpcConnectionAdapter(await host.connectHop(genesis, endpoint), onResponse, onClosed); + }; +} +/** Chain and HOP share response pumping and exactly-once transport cleanup. */ +function rpcConnectionAdapter(connection, onResponse, onClosed) { + let closed = false; + let stopResponses; + const close = (notify) => { + if (closed) + return; + closed = true; + stopResponses?.(); + try { + connection.close(); + } + finally { + if (notify) + onClosed?.(); + } + }; + try { + stopResponses = pumpIterator(connection.responses()[Symbol.asyncIterator](), onResponse, "JSON-RPC responses", undefined, () => { + try { + close(true); + } + catch { + console.error("[truapi host callbacks] JSON-RPC close failed"); + } + }); + // A synchronous iterator failure can close before pumpIterator returns. + if (closed) + stopResponses(); + } + catch (err) { + close(false); + throw err; + } + return { + send(request) { + if (closed) + throw new Error("JSON-RPC connection is closed"); + try { connection.send(request); - }, - close() { - stopResponses(); - connection.close(); - }, - }; + } + catch (err) { + close(true); + throw err; + } + }, + close: () => close(false), }; } 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 96fc109d0..28dd67f4f 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks-adapter.d.ts +++ b/vendor/truapi-host/dist/generated/host-callbacks-adapter.d.ts @@ -1,6 +1,6 @@ import type { GenericError } from "@parity/truapi"; import type { RequiredHostCallbacks } from "./host-callbacks.js"; -import type { ChainConnect } from "../runtime.js"; +import type { ChainConnect, HopConnect } from "../runtime.js"; /** * Byte-oriented callback surface the WASM core invokes. Members of an * optional capability are absent when the host omits the capability; @@ -13,6 +13,7 @@ export interface RawCallbacks { registerChatBot?(product: Uint8Array, request: Uint8Array): Promise; postChatMessage?(product: Uint8Array, request: Uint8Array): Promise; subscribeChatRooms?(product: Uint8Array, sendItem: (item?: Uint8Array) => void, sendError: (error: GenericError) => void): (() => void) | void; + nativeCoinage?(request: Uint8Array): Promise; contacts?(lookup: Uint8Array): Promise; pickContact?(product: Uint8Array): Promise; readCoreStorage(key: Uint8Array): Promise; @@ -20,8 +21,18 @@ export interface RawCallbacks { clearCoreStorage(key: Uint8Array): Promise; featureSupported(request: Uint8Array): Promise; supportedChains(): Promise; + allowedHopEndpoints(bulletinGenesisHash: Uint8Array): Promise; + hopConnect: HopConnect; + identityUsernameCandidates?(username: string, peopleChainGenesisHash: Uint8Array): Promise; subscribeLocale(sendItem: (item?: Uint8Array) => void, sendError: (error: GenericError) => void): (() => void) | void; localizeTimestamps(request: Uint8Array): Promise; + pickChatFiles(request: Uint8Array): Promise; + readChatFile(sourceId: string, offset: bigint, length: number): Promise; + releaseChatFile(sourceId: string): Promise; + beginChatFileExport(request: Uint8Array): Promise; + writeChatFileExport(exportId: string, offset: bigint, data: Uint8Array): Promise; + finishChatFileExport(exportId: string): Promise; + cancelChatFileExport(exportId: string): Promise; navigateTo(url: string): Promise; pushNotification(notification: Uint8Array): Promise; cancelNotification(id: number): Promise; diff --git a/vendor/truapi-host/dist/generated/host-callbacks-adapter.js b/vendor/truapi-host/dist/generated/host-callbacks-adapter.js index 83622fff7..8e740f168 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks-adapter.js +++ b/vendor/truapi-host/dist/generated/host-callbacks-adapter.js @@ -4,16 +4,24 @@ // callback surface the WASM core invokes. Codec-backed wire and // 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, PermissionDecision, ProductContext, UserConfirmationReview, } from "./host-callbacks.js"; -import { chainConnectAdapter, driveResultStream, } from "../adapter-support.js"; +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"; +const allowedHopEndpointsResultCodec = S.Vector(S.str); +const identityUsernameCandidatesResultCodec = S.Vector(S.Bytes(32)); +const pickChatFilesResultCodec = S.Vector(NativeChatPickedFile); /** Adapt typed host callbacks into the raw SCALE callback surface the * WASM core invokes. */ export function createWasmRawCallbacks(callbacks) { const chat = callbacks.chat; + const coinageWallet = coinageWalletHostAdapter(callbacks.coinageWallet); const contacts = callbacks.contacts; + const identityBackend = callbacks.identityBackend; const permissionStatus = callbacks.permissionStatus; const pocket = callbacks.pocket; + const hop = callbacks.hop ?? unavailableHopProvider; + const nativeChatFiles = callbacks.nativeChatFiles ?? unavailableNativeChatFilesHost; return { authStateChanged: async (state) => await callbacks.auth.authStateChanged(AuthState.dec(state)), chainConnect: chainConnectAdapter(callbacks.chain), @@ -25,6 +33,11 @@ export function createWasmRawCallbacks(callbacks) { subscribeChatRooms: (product, sendItem, sendError) => driveResultStream(chat.subscribeChatRooms(ProductContext.dec(product)), (item) => sendItem(HostChatListSubscribeItem.enc(item)), sendError), } : {}), + ...(coinageWallet + ? { + nativeCoinage: async (request) => NativeCoinageResponse.enc(await coinageWallet.nativeCoinage(NativeCoinageRequest.dec(request))), + } + : {}), ...(contacts ? { contacts: async (lookup) => HostContactMatches.enc(await contacts.contacts(HostContactLookup.dec(lookup))), @@ -36,8 +49,22 @@ export function createWasmRawCallbacks(callbacks) { clearCoreStorage: async (key) => await callbacks.coreStorage.clearCoreStorage(CoreStorageKey.dec(key)), featureSupported: async (request) => HostFeatureSupportedResponse.enc(await callbacks.features.featureSupported(HostFeatureSupportedRequest.dec(request))), supportedChains: async () => HostChainSet.enc(await callbacks.features.supportedChains()), + allowedHopEndpoints: async (bulletinGenesisHash) => allowedHopEndpointsResultCodec.enc(await hop.allowedHopEndpoints(bulletinGenesisHash)), + hopConnect: hopConnectAdapter(hop), + ...(identityBackend + ? { + identityUsernameCandidates: async (username, peopleChainGenesisHash) => identityUsernameCandidatesResultCodec.enc(await identityBackend.identityUsernameCandidates(username, peopleChainGenesisHash)), + } + : {}), subscribeLocale: (sendItem, sendError) => driveResultStream(callbacks.locale.subscribeLocale(), (item) => sendItem(HostLocaleSubscribeItem.enc(item)), sendError), localizeTimestamps: async (request) => HostLocaleLocalizeTimestampsResponse.enc(await callbacks.locale.localizeTimestamps(HostLocaleLocalizeTimestampsRequest.dec(request))), + pickChatFiles: async (request) => pickChatFilesResultCodec.enc(await nativeChatFiles.pickChatFiles(NativeChatFilePickRequest.dec(request))), + readChatFile: async (sourceId, offset, length) => await nativeChatFiles.readChatFile(sourceId, offset, length), + releaseChatFile: async (sourceId) => await nativeChatFiles.releaseChatFile(sourceId), + beginChatFileExport: async (request) => await nativeChatFiles.beginChatFileExport(NativeChatFileExportRequest.dec(request)), + writeChatFileExport: async (exportId, offset, data) => await nativeChatFiles.writeChatFileExport(exportId, offset, data), + finishChatFileExport: async (exportId) => await nativeChatFiles.finishChatFileExport(exportId), + cancelChatFileExport: async (exportId) => await nativeChatFiles.cancelChatFileExport(exportId), navigateTo: async (url) => await callbacks.navigation.navigateTo(url), pushNotification: async (notification) => HostPushNotificationResponse.enc(await callbacks.notifications.pushNotification(HostPushNotificationRequest.dec(notification))), cancelNotification: async (id) => await callbacks.notifications.cancelNotification(id), diff --git a/vendor/truapi-host/dist/generated/host-callbacks.d.ts b/vendor/truapi-host/dist/generated/host-callbacks.d.ts index 99f5fcb63..eb370561f 100644 --- a/vendor/truapi-host/dist/generated/host-callbacks.d.ts +++ b/vendor/truapi-host/dist/generated/host-callbacks.d.ts @@ -1,5 +1,5 @@ import * as S from "@parity/truapi/scale"; -import { AllocatableResource, Bytes32, ChainIdentifier, HostAccountSignVrfRequest, HostDevicePermissionRequest, HostSignPayloadRequest, HostSignPayloadWithLegacyAccountRequest, HostSignRawRequest, HostSignRawWithLegacyAccountRequest, LegacyAccountTxPayload, ProductAccountId, ProductAccountTxPayload, ProductProofContext, RemotePermissionRequest, RingLocation } from "@parity/truapi"; +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"; /** * Review shown before a product asks to access another product account. @@ -81,6 +81,15 @@ export type AuthState = tag: "Authenticating"; value?: undefined; }; +/** + * Review shown before a product binds or uses wallet-held Chat identity authority. + */ +export interface ChatAuthorityReview { + /** + * Product requesting the Chat identity operation. + */ + productId: string; +} /** * Core-owned host-private storage slots. Products never address these slots; * the host chooses the backing store for each slot. @@ -218,6 +227,57 @@ export type CoreStorageKey = value: { productId: string; }; +} +/** + * Encrypted main-purse inventory, operation journal, and claim recovery state. + * + * This slot is wallet-owned, not product-owned, and must survive clearing a + * product's data. Writes replace the entire value atomically. + */ + | { + tag: "MainPurseCoinage"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + }; +} +/** + * Encrypted Host-owned native Chat device, peer roster, and migration state. + */ + | { + tag: "NativeChatDevice"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + productId: string; + }; +} +/** + * One encrypted, bounded native Chat attachment cache chunk. + * Values use the Chat state's wallet-bound authenticated encryption. + */ + | { + tag: "NativeChatFileChunk"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + productId: string; + attachmentId: Uint8Array; + chunkIndex: number; + }; +} +/** + * Previously initialized Chat products to restore after this wallet unlocks. + * + * This is a host-private wallet-owned index, not a permission grant. The + * core rechecks each product's current grants before restoring reception. + */ + | { + tag: "NativeChatProducts"; + value: { + rootPublicKey: Uint8Array; + genesisHash: Uint8Array; + }; }; /** * Review shown before a product creates a ring-VRF proof (RFC 0004). @@ -383,6 +443,363 @@ export interface IdentityDisclosureReview { * than only display it. */ export type LoginFailureKind = "NoFreeAllowanceSlots" | "Other"; +/** + * Exact Host-resolved payment reviewed before debiting the user's main purse. + * + * This review never grants a reusable spending permission. Chat authority and + * automatic product signing do not authorize it. + */ +export interface MainPurseChatPaymentReview { + /** + * Authenticated product requesting this payment. + */ + callingProductId: string; + /** + * Recipient identity authenticated by the Host's native Chat session. + */ + recipientIdentity: Uint8Array; + /** + * Host-resolved username for that identity, never a product display label. + */ + recipientUsername?: string; + /** + * Exact recipient amount in cents of the selected Coinage asset. + */ + amountCents: bigint; + /** + * Maximum main-purse debit, including any approved fee, in the same cents. + */ + maxDebitCents: bigint; + /** + * Genesis hash of the Host-selected Coinage chain. + */ + genesisHash: Uint8Array; + /** + * Trusted Coinage asset instance; `undefined` denotes a legacy single-asset runtime. + */ + coinageInstanceId?: number; + /** + * Immutable, wallet-scoped payment operation being authorized. + */ + operationId: Uint8Array; +} +/** + * Trusted context for exporting a verified native Chat attachment. + */ +export interface NativeChatFileExportRequest { + /** + * Authenticated product requesting presentation. + */ + productId: string; + /** + * Host-authenticated peer identity. + */ + peerIdentity: Uint8Array; + /** + * Host-resolved peer name, if available. + */ + peerUsername?: string; + /** + * Verified attachment metadata, including the exact export size. + */ + metadata: HostNativeChatAttachmentMetadata; +} +/** + * Trusted native Chat selection context; never passed to a product. + */ +export interface NativeChatFilePickRequest { + /** + * Authenticated product requesting selection. + */ + productId: string; + /** + * Host-authenticated recipient identity. + */ + peerIdentity: Uint8Array; + /** + * Host-resolved recipient name, if available. + */ + peerUsername?: string; + /** + * Maximum number of files the Host can accept. + */ + maxFiles: number; +} +/** + * Immutable Host-owned source and metadata derived from its actual bytes. + */ +export interface NativeChatPickedFile { + /** + * Opaque private handle surviving restart until explicitly released. + */ + sourceId: string; + /** + * Actual source size and native media metadata. + */ + metadata: HostNativeChatAttachmentMetadata; +} +/** + * Sanitized failures. Never forward secret-bearing native exception descriptions. + */ +export type NativeCoinageFailure = "Unavailable" | "InvalidRequest" | "InvalidSource" | "OperationConflict" | "OperationNotFound" | "InsufficientBalance" | "UserRejected"; +/** + * Host-private bearer material. Never return this through the product API or log it. + * Raw amounts are canonical unsigned decimal u128 strings, avoiding FFI truncation. + */ +export interface NativeCoinageMemo { + /** + * Validated 64-byte native sr25519 secret keys, confined to the trusted Host. + */ + secretKeys: Array; + /** + * Exact total in canonical decimal raw chain units. + */ + totalValueRaw: string; +} +/** + * Durable native-wallet operations, not an alternative inventory ledger. + */ +export type NativeCoinageOperation = +/** + * Read trusted denomination metadata without selecting or allocating inventory. + */ +{ + tag: "Denomination"; + value?: undefined; +} +/** + * Native trusted UI must review the exact intent and maximum debit before spending. + * Replays must reuse persisted preparation, never allocate a second payment. + * Before returning a memo, native custody must survive restart atomically with + * transaction registration. Startup must never release these coins as provisional. + */ + | { + tag: "PreparePayment"; + value: { + intent: NativeCoinagePaymentIntent; + }; +} +/** + * Called only after the authenticated Host durably accepts encrypted delivery. + * Records transport acceptance; it is not the first durable native custody mark. + */ + | { + tag: "CommitHandoff"; + value: { + productId: string; + operationId: Uint8Array; + }; +} +/** + * Immutable public cards; do not initialize or claim an unrelated wallet. + */ + | { + tag: "Views"; + value: { + productId: string; + }; +} +/** + * Accepted ids come from the Host's durable ciphertext custody ledger. + */ + | { + tag: "PendingHandoffs"; + value: { + productId: string; + acceptedOperations: Array; + }; +} +/** + * Read an existing recoverable handoff without approval, selection or spending. + */ + | { + tag: "ReadHandoff"; + value: { + productId: string; + operationId: Uint8Array; + }; +} +/** + * Peer acknowledgment is not monetary settlement. + */ + | { + tag: "NoteDelivery"; + value: { + productId: string; + operationId: Uint8Array; + }; +} +/** + * Resume already-owned work only; never authorize a fresh debit. + */ + | { + tag: "Reconcile"; + value?: undefined; +} +/** + * Persist source custody before returning. Only finalized credit is successful. + * Reordered sources reuse the same id; changed minimum or overlapping custody conflicts. + */ + | { + tag: "TopUp"; + value: { + productId: string; + operationId: Uint8Array; + minimumAmountRaw: string; + secretKeys: Array; + }; +}; +/** + * Immutable, Host-authenticated outgoing intent. No field is a product display hint. + */ +export interface NativeCoinagePaymentIntent { + /** + * Stable wallet-, network- and product-scoped operation identity. + */ + operationId: Uint8Array; + /** + * Authenticated calling product, not a guest-provided display name. + */ + productId: string; + /** + * Original caller request identifier, bound immutably to this intent. + */ + requestId: string; + /** + * Recipient identity authenticated by the Host's Chat authority. + */ + peerIdentity: Uint8Array; + /** + * Independently resolved recipient name, when available. + */ + recipientUsername?: string; + /** + * Positive recipient amount in cents of the configured Coinage asset. + */ + amountCents: bigint; +} +/** + * One native operation with the immutable wallet/network scope to authenticate. + */ +export interface NativeCoinageRequest { + /** + * Expected owner and asset, verified against the active native wallet. + */ + scope: NativeCoinageScope; + /** + * Host-private command; incoming sources must never be logged. + */ + operation: NativeCoinageOperation; +} +/** + * Typed native results. Only the trusted Host may consume a Prepared memo. + */ +export type NativeCoinageResponse = +/** + * Trusted denomination metadata for the selected wallet/asset. + */ +{ + tag: "Denomination"; + value: { + centsUnitRaw: string; + }; +} +/** + * Existing durable native preparation, or a terminal public payment. + */ + | { + tag: "Prepared"; + value: { + payment: HostNativeChatPayment; + memo?: NativeCoinageMemo; + }; +} +/** + * Product-scoped public payment cards, never a spendable balance. + */ + | { + tag: "Payments"; + value: { + payments: Array; + }; +} +/** + * Result of an incoming custody operation. + */ + | { + tag: "TopUp"; + value: { + outcome: NativeCoinageTopUpOutcome; + }; +} +/** + * The requested metadata transition or recovery pass completed. + */ + | { + tag: "Done"; + value?: undefined; +} +/** + * Sanitized domain rejection; cannot authorize another backend. + */ + | { + tag: "Failed"; + value: { + reason: NativeCoinageFailure; + }; +}; +/** + * Wallet and asset binding checked by the native service before every operation. + */ +export interface NativeCoinageScope { + /** + * Authenticated root key of the wallet owning the main purse. + */ + rootPublicKey: Uint8Array; + /** + * Genesis hash of the configured Coinage chain. + */ + genesisHash: Uint8Array; + /** + * Configured asset instance; `undefined` denotes a legacy single-asset runtime. + */ + coinageInstanceId?: number; +} +/** + * Incoming settlement result; acceptance and best-head observations are not finality. + */ +export type NativeCoinageTopUpOutcome = +/** + * The original requested minimum has been credited at finality. + * For a zero minimum, the source claim is terminal with positive finalized credit. + */ +{ + tag: "Cleared"; + value?: undefined; +} +/** + * Terminal shortfall, expressed in raw chain units, not cents. + */ + | { + tag: "Partial"; + value: { + creditedAmountRaw: string; + }; +} +/** + * Durable custody exists, but final credit has not been established. + */ + | { + tag: "Pending"; + value?: undefined; +} +/** + * Terminal: none of the requested funds could be claimed. + */ + | { + tag: "NotClaimed"; + value?: undefined; +}; /** * Permission request whose authorization status can be inspected or updated * by host administration UI. @@ -417,6 +834,22 @@ export type PermissionAuthorizationRequest = value: { targetProductId: string; }; +} +/** + * Product-scoped permission to bind and use wallet-held Chat identity authority. + */ + | { + tag: "ChatAuthority"; + value?: undefined; +} +/** + * Product-scoped permission to ensure Statement Store quota, not increase it. + */ + | { + tag: "StatementStoreAllowance"; + value: { + derivationIndex?: DerivationIndex; + }; }; /** * Authorization status for a permission request. @@ -708,6 +1141,20 @@ export type UserConfirmationReview = | { tag: "ProductSubtree"; value: ProductSubtreeReview; +} +/** + * Allow a product to bind and use wallet-held Chat identity authority. + */ + | { + tag: "ChatAuthority"; + value: ChatAuthorityReview; +} +/** + * Confirm this exact main-purse payment; never eligible for auto-approval. + */ + | { + tag: "MainPurseChatPayment"; + value: MainPurseChatPaymentReview; }; /** * Review shown before a product asks to access another product account. @@ -723,6 +1170,10 @@ export declare const AccountAliasReview: S.Codec; * and never derive auth UI from any other signal. */ 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; /** * Core-owned host-private storage slots. Products never address these slots; * the host chooses the backing store for each slot. @@ -786,6 +1237,58 @@ export declare const IdentityDisclosureReview: S.Codec * than only display it. */ export declare const LoginFailureKind: S.Codec; +/** + * Exact Host-resolved payment reviewed before debiting the user's main purse. + * + * This review never grants a reusable spending permission. Chat authority and + * automatic product signing do not authorize it. + */ +export declare const MainPurseChatPaymentReview: S.Codec; +/** + * Trusted context for exporting a verified native Chat attachment. + */ +export declare const NativeChatFileExportRequest: S.Codec; +/** + * Trusted native Chat selection context; never passed to a product. + */ +export declare const NativeChatFilePickRequest: S.Codec; +/** + * Immutable Host-owned source and metadata derived from its actual bytes. + */ +export declare const NativeChatPickedFile: S.Codec; +/** + * Sanitized failures. Never forward secret-bearing native exception descriptions. + */ +export declare const NativeCoinageFailure: S.Codec; +/** + * Host-private bearer material. Never return this through the product API or log it. + * Raw amounts are canonical unsigned decimal u128 strings, avoiding FFI truncation. + */ +export declare const NativeCoinageMemo: S.Codec; +/** + * Durable native-wallet operations, not an alternative inventory ledger. + */ +export declare const NativeCoinageOperation: S.Codec; +/** + * Immutable, Host-authenticated outgoing intent. No field is a product display hint. + */ +export declare const NativeCoinagePaymentIntent: S.Codec; +/** + * One native operation with the immutable wallet/network scope to authenticate. + */ +export declare const NativeCoinageRequest: S.Codec; +/** + * Typed native results. Only the trusted Host may consume a Prepared memo. + */ +export declare const NativeCoinageResponse: S.Codec; +/** + * Wallet and asset binding checked by the native service before every operation. + */ +export declare const NativeCoinageScope: S.Codec; +/** + * Incoming settlement result; acceptance and best-head observations are not finality. + */ +export declare const NativeCoinageTopUpOutcome: S.Codec; /** * Permission request whose authorization status can be inspected or updated * by host administration UI. @@ -939,6 +1442,19 @@ export interface ChatPlatform { */ subscribeChatRooms(product: ProductContext): AsyncIterable>; } +/** + * Optional native wallet service boundary, never exposed to products. + * + * Injecting this service at runtime construction assigns native custody for + * the runtime's lifetime. Absence selects the built-in Rust wallet; native + * unavailability or failure never permits Rust fallback. + */ +export interface CoinageWalletHost { + /** + * Invoke the selected native owner. An error never permits Rust fallback. + */ + nativeCoinage(request: NativeCoinageRequest): Promise; +} /** * Host-owned contact picker, drawn from the chat lists the host's chat * extensions hold. @@ -1084,10 +1600,10 @@ export interface CoreAdmin { * they accumulate for the life of the install. * * `describe_core_storage_key` names the product owning a slot: - * `CoreStorageKeyDescription::product_id` is `Some` exactly for the - * product-indexed variants, which are `PermissionAuthorization`, - * `AutoSigningKey`, and `ProductSubtree`. Keying host storage by that value - * makes the sweep a prefix delete rather than a scan. + * `CoreStorageKeyDescription::product_id` is `Some` for product-indexed + * slots, including the encrypted attachment chunk cache. Wallet-owned state + * remains outside that sweep. Keying host storage by this metadata makes + * product removal a prefix delete rather than a scan. */ export interface CoreStorage { /** @@ -1118,6 +1634,38 @@ export interface Features { */ supportedChains(): Promise; } +/** + * Host-private HOP transport for the configured Bulletin chain. + * + * Endpoints are trusted host configuration, never product-supplied dialing + * instructions. Implementations must re-read their allowlist and enforce exact + * URL membership before opening a connection. An unconfigured host is + * explicitly unavailable; it must not fall back to a chain RPC endpoint. + */ +export interface HopProvider { + /** + * Current exact WSS endpoints from the host's trusted Bulletin registry. + */ + allowedHopEndpoints?(bulletinGenesisHash: Uint8Array): Promise>; + /** + * Open one private HOP connection, sharing the JSON-RPC lifecycle only. + * The caller closes the returned lease when the private operation ends. + */ + connectHop?(bulletinGenesisHash: Uint8Array, endpoint: string): Promise; +} +/** + * Optional host-authenticated username candidate source. The host owns backend + * configuration and credentials. Candidates are never ownership assertions: + * the core checks finalized dotNS ownership and the canonical People Chat key. + */ +export interface IdentityBackendHost { + /** + * Return exact-name candidates on the specified People network. Reject + * unavailable configuration/authentication and incomplete search results. + * Neither a guest URL nor a backend display label crosses this boundary. + */ + identityUsernameCandidates(username: string, peopleChainGenesisHash: Uint8Array): Promise>; +} /** * A live JSON-RPC connection to a chain. */ @@ -1151,6 +1699,47 @@ export interface LocaleHost { */ localizeTimestamps?(request: HostLocaleLocalizeTimestampsRequest): Promise; } +/** + * Host-private native Chat selection, immutable custody and safe export. + * + * Handles, file bytes and destinations must never be exposed to products. + * Optional embedders without a backend must fail explicitly as unavailable. + */ +export interface NativeChatFilesHost { + /** + * Present trusted selection and durably snapshot the selected files. + * An empty result denotes user cancellation, not an unavailable backend. + */ + pickChatFiles(request: NativeChatFilePickRequest): Promise>; + /** + * Read exactly `length` bytes from an immutable source. Reject lengths + * above 2,000,000 and checked ranges extending beyond its actual u32 size. + */ + readChatFile(sourceId: string, offset: bigint, length: number): Promise; + /** + * Release durable source custody. Repeated release is harmless. + */ + releaseChatFile(sourceId: string): Promise; + /** + * Present trusted export consent and create a private partial output. + * ``undefined`` denotes user cancellation. Never overwrite without consent. + */ + beginChatFileExport(request: NativeChatFileExportRequest): Promise; + /** + * Append a bounded chunk at the exact current offset; never allow holes, + * rewrites, or bytes beyond the declared export size. + */ + writeChatFileExport(exportId: string, offset: bigint, data: Uint8Array): Promise; + /** + * Publish only an exact-size completed output through safe native UI. + * Never automatically execute HTML, SVG, scripts, or other active files. + */ + finishChatFileExport(exportId: string): Promise; + /** + * Idempotently discard a partial output, never a completed user export. + */ + cancelChatFileExport(exportId: string): Promise; +} /** * Open URLs in the system browser. Input is already trimmed, categorized, * and (where needed) normalized by the core; the host implementation only @@ -1353,8 +1942,8 @@ export interface UserConfirmation { } /** * Combined platform interface. A host must provide every capability trait - * listed here. Members marked optional may be omitted; the core answers their - * product calls with `Unsupported`. See `OptionalPlatform`. + * listed here. Optional capabilities are declared separately in + * `OptionalPlatform`. */ export interface HostCallbacks { navigation: Navigation; @@ -1364,6 +1953,8 @@ export interface HostCallbacks { productStorage: ProductStorage; coreStorage: CoreStorage; chain: ChainProvider; + hop?: HopProvider; + nativeChatFiles?: NativeChatFilesHost; auth: AuthPresenter; userConfirmation: UserConfirmation; theme: ThemeHost; @@ -1371,7 +1962,9 @@ export interface HostCallbacks { preimage: PreimageHost; productOperations: ProductOperations; chat?: ChatPlatform; + coinageWallet?: CoinageWalletHost; contacts?: ContactsPlatform; + identityBackend?: IdentityBackendHost; permissionStatus?: PermissionStatusHost; pocket?: PocketPlatform; } @@ -1383,6 +1976,8 @@ export interface RequiredHostCallbacks { productStorage: Required; coreStorage: Required; chain: Required; + hop?: Required; + nativeChatFiles?: Required; auth: Required; userConfirmation: Required; theme: Required; @@ -1390,7 +1985,9 @@ export interface RequiredHostCallbacks { preimage: Required; productOperations: Required; chat?: Required; + coinageWallet?: Required; contacts?: Required; + identityBackend?: Required; permissionStatus?: Required; pocket?: Required; } diff --git a/vendor/truapi-host/dist/generated/host-callbacks.js b/vendor/truapi-host/dist/generated/host-callbacks.js index 037fece2b..6ad1c295f 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, HostAccountSignVrfRequest, HostDevicePermissionRequest, HostSignPayloadRequest, HostSignPayloadWithLegacyAccountRequest, HostSignRawRequest, HostSignRawWithLegacyAccountRequest, LegacyAccountTxPayload, ProductAccountId, ProductAccountTxPayload, ProductProofContext, RemotePermissionRequest, RingLocation, } from "@parity/truapi"; +import { AllocatableResource, 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. */ @@ -19,6 +19,10 @@ export const AccountAliasReview = S.lazy(() => S.Struct({ callingProductId: S.st * and never derive auth UI from any other signal. */ export const 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 })); +/** + * Review shown before a product binds or uses wallet-held Chat identity authority. + */ +export const ChatAuthorityReview = S.lazy(() => S.Struct({ productId: S.str })); /** * Core-owned host-private storage slots. Products never address these slots; * the host chooses the backing store for each slot. @@ -26,7 +30,7 @@ export const AuthState = S.lazy(() => S.TaggedUnion({ Disconnected: S._void, Pai * 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 }) })); +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) }) })); /** * Review shown before a product creates a ring-VRF proof (RFC 0004). */ @@ -82,11 +86,63 @@ export const IdentityDisclosureReview = S.lazy(() => S.Struct({ productId: S.str * than only display it. */ export const LoginFailureKind = S.lazy(() => S.Status("NoFreeAllowanceSlots", "Other")); +/** + * Exact Host-resolved payment reviewed before debiting the user's main purse. + * + * This review never grants a reusable spending permission. Chat authority and + * automatic product signing do not authorize it. + */ +export const 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) })); +/** + * Trusted context for exporting a verified native Chat attachment. + */ +export const NativeChatFileExportRequest = S.lazy(() => S.Struct({ productId: S.str, peerIdentity: S.Bytes(32), peerUsername: S.Option(S.str), metadata: HostNativeChatAttachmentMetadata })); +/** + * Trusted native Chat selection context; never passed to a product. + */ +export const NativeChatFilePickRequest = S.lazy(() => S.Struct({ productId: S.str, peerIdentity: S.Bytes(32), peerUsername: S.Option(S.str), maxFiles: S.u32 })); +/** + * Immutable Host-owned source and metadata derived from its actual bytes. + */ +export const NativeChatPickedFile = S.lazy(() => S.Struct({ sourceId: S.str, metadata: HostNativeChatAttachmentMetadata })); +/** + * Sanitized failures. Never forward secret-bearing native exception descriptions. + */ +export const NativeCoinageFailure = S.lazy(() => S.Status("Unavailable", "InvalidRequest", "InvalidSource", "OperationConflict", "OperationNotFound", "InsufficientBalance", "UserRejected")); +/** + * Host-private bearer material. Never return this through the product API or log it. + * Raw amounts are canonical unsigned decimal u128 strings, avoiding FFI truncation. + */ +export const NativeCoinageMemo = S.lazy(() => S.Struct({ secretKeys: S.Vector(S.Bytes()), totalValueRaw: S.str })); +/** + * Durable native-wallet operations, not an alternative inventory ledger. + */ +export const NativeCoinageOperation = S.lazy(() => S.TaggedUnion({ Denomination: S._void, PreparePayment: S.Struct({ intent: NativeCoinagePaymentIntent }), CommitHandoff: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), Views: S.Struct({ productId: S.str }), PendingHandoffs: S.Struct({ productId: S.str, acceptedOperations: S.Vector(S.Bytes(32)) }), ReadHandoff: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), NoteDelivery: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), Reconcile: S._void, TopUp: S.Struct({ productId: S.str, operationId: S.Bytes(32), minimumAmountRaw: S.str, secretKeys: S.Vector(S.Bytes()) }) })); +/** + * Immutable, Host-authenticated outgoing intent. No field is a product display hint. + */ +export const NativeCoinagePaymentIntent = S.lazy(() => S.Struct({ operationId: S.Bytes(32), productId: S.str, requestId: S.str, peerIdentity: S.Bytes(32), recipientUsername: S.Option(S.str), amountCents: S.u64 })); +/** + * One native operation with the immutable wallet/network scope to authenticate. + */ +export const NativeCoinageRequest = S.lazy(() => S.Struct({ scope: NativeCoinageScope, operation: NativeCoinageOperation })); +/** + * Typed native results. Only the trusted Host may consume a Prepared memo. + */ +export const NativeCoinageResponse = S.lazy(() => S.TaggedUnion({ Denomination: S.Struct({ centsUnitRaw: S.str }), Prepared: S.Struct({ payment: HostNativeChatPayment, memo: S.Option(NativeCoinageMemo) }), Payments: S.Struct({ payments: S.Vector(HostNativeChatPayment) }), TopUp: S.Struct({ outcome: NativeCoinageTopUpOutcome }), Done: S._void, Failed: S.Struct({ reason: NativeCoinageFailure }) })); +/** + * Wallet and asset binding checked by the native service before every operation. + */ +export const NativeCoinageScope = S.lazy(() => S.Struct({ rootPublicKey: S.Bytes(32), genesisHash: S.Bytes(32), coinageInstanceId: S.Option(S.u32) })); +/** + * Incoming settlement result; acceptance and best-head observations are not finality. + */ +export const NativeCoinageTopUpOutcome = S.lazy(() => S.TaggedUnion({ Cleared: S._void, Partial: S.Struct({ creditedAmountRaw: S.str }), Pending: S._void, NotClaimed: S._void })); /** * 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 }) })); +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) }) })); /** * Authorization status for a permission request. * @@ -159,4 +215,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 })); +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 })); diff --git a/vendor/truapi-host/dist/generated/worker-callbacks.d.ts b/vendor/truapi-host/dist/generated/worker-callbacks.d.ts index 03132e6bd..e66f8be5b 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 } from "../runtime.js"; -export declare const CALLBACK_NAMES: readonly ["authStateChanged", "createChatRoom", "registerChatBot", "postChatMessage", "contacts", "pickContact", "readCoreStorage", "writeCoreStorage", "clearCoreStorage", "featureSupported", "supportedChains", "localizeTimestamps", "navigateTo", "pushNotification", "cancelNotification", "devicePermissionStatus", "devicePermission", "remotePermission", "removePocketCard", "beginOperation", "endOperation", "read", "write", "clear", "confirmPermission", "confirmUserAction"]; +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 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]; @@ -9,18 +9,23 @@ export interface WorkerCallbackBridge { callbackRequest(name: CallbackName, args: readonly unknown[]): Promise; startSubscription(name: SubscriptionName, payload: Uint8Array | string | null, sendItem: (value: T) => void, sendError: (error: GenericError) => void): () => void; chainConnect: ChainConnect; + hopConnect: HopConnect; } /** * Optional capabilities the main-thread host actually serves. A * capability left out here is not proxied into the worker, so the - * core answers its product calls with `Unsupported`. + * core applies that capability's absence behavior. */ export interface OptionalCapabilities { /** Whether the host serves this capability. */ chat?: boolean; /** Whether the host serves this capability. */ + coinageWallet?: boolean; + /** Whether the host serves this capability. */ contacts?: boolean; /** Whether the host serves this capability. */ + identityBackend?: boolean; + /** Whether the host serves this capability. */ permissionStatus?: boolean; /** Whether the host serves this capability. */ pocket?: boolean; diff --git a/vendor/truapi-host/dist/generated/worker-callbacks.js b/vendor/truapi-host/dist/generated/worker-callbacks.js index 3bae9ca5f..a3f9d73a0 100644 --- a/vendor/truapi-host/dist/generated/worker-callbacks.js +++ b/vendor/truapi-host/dist/generated/worker-callbacks.js @@ -9,6 +9,7 @@ export const CALLBACK_NAMES = [ "createChatRoom", "registerChatBot", "postChatMessage", + "nativeCoinage", "contacts", "pickContact", "readCoreStorage", @@ -16,7 +17,16 @@ export const CALLBACK_NAMES = [ "clearCoreStorage", "featureSupported", "supportedChains", + "allowedHopEndpoints", + "identityUsernameCandidates", "localizeTimestamps", + "pickChatFiles", + "readChatFile", + "releaseChatFile", + "beginChatFileExport", + "writeChatFileExport", + "finishChatFileExport", + "cancelChatFileExport", "navigateTo", "pushNotification", "cancelNotification", @@ -48,7 +58,15 @@ function rawCallbacks(bridge) { clearCoreStorage: (key) => bridge.callbackRequest("clearCoreStorage", [key]), featureSupported: (request) => bridge.callbackRequest("featureSupported", [request]), supportedChains: () => bridge.callbackRequest("supportedChains", []), + allowedHopEndpoints: (bulletinGenesisHash) => bridge.callbackRequest("allowedHopEndpoints", [bulletinGenesisHash]), localizeTimestamps: (request) => bridge.callbackRequest("localizeTimestamps", [request]), + pickChatFiles: (request) => bridge.callbackRequest("pickChatFiles", [request]), + readChatFile: (sourceId, offset, length) => bridge.callbackRequest("readChatFile", [sourceId, offset, length]), + releaseChatFile: (sourceId) => bridge.callbackRequest("releaseChatFile", [sourceId]), + beginChatFileExport: (request) => bridge.callbackRequest("beginChatFileExport", [request]), + writeChatFileExport: (exportId, offset, data) => bridge.callbackRequest("writeChatFileExport", [exportId, offset, data]), + finishChatFileExport: (exportId) => bridge.callbackRequest("finishChatFileExport", [exportId]), + cancelChatFileExport: (exportId) => bridge.callbackRequest("cancelChatFileExport", [exportId]), navigateTo: (url) => bridge.callbackRequest("navigateTo", [url]), pushNotification: (notification) => bridge.callbackRequest("pushNotification", [notification]), cancelNotification: (id) => bridge.callbackRequest("cancelNotification", [id]), @@ -79,12 +97,22 @@ function chatRawCallbacks(bridge) { subscribeChatRooms: (product, sendItem, sendError) => bridge.startSubscription("subscribeChatRooms", product, sendItem, sendError), }; } +function coinageWalletRawCallbacks(bridge) { + return { + nativeCoinage: (request) => bridge.callbackRequest("nativeCoinage", [request]), + }; +} function contactsRawCallbacks(bridge) { return { contacts: (lookup) => bridge.callbackRequest("contacts", [lookup]), pickContact: (product) => bridge.callbackRequest("pickContact", [product]), }; } +function identityBackendRawCallbacks(bridge) { + return { + identityUsernameCandidates: (username, peopleChainGenesisHash) => bridge.callbackRequest("identityUsernameCandidates", [username, peopleChainGenesisHash]), + }; +} function permissionStatusRawCallbacks(bridge) { return { devicePermissionStatus: (request) => bridge.callbackRequest("devicePermissionStatus", [request]), @@ -101,11 +129,16 @@ export function createWorkerRawCallbacks(bridge, capabilities = {}) { ...rawCallbacks(bridge), ...subscriptionRawCallbacks(bridge), chainConnect: bridge.chainConnect, + hopConnect: bridge.hopConnect, }; if (capabilities.chat) Object.assign(callbacks, chatRawCallbacks(bridge)); + if (capabilities.coinageWallet) + Object.assign(callbacks, coinageWalletRawCallbacks(bridge)); if (capabilities.contacts) Object.assign(callbacks, contactsRawCallbacks(bridge)); + if (capabilities.identityBackend) + Object.assign(callbacks, identityBackendRawCallbacks(bridge)); if (capabilities.permissionStatus) Object.assign(callbacks, permissionStatusRawCallbacks(bridge)); if (capabilities.pocket) diff --git a/vendor/truapi-host/dist/runtime.d.ts b/vendor/truapi-host/dist/runtime.d.ts index c53757ee7..bd7493ac4 100644 --- a/vendor/truapi-host/dist/runtime.d.ts +++ b/vendor/truapi-host/dist/runtime.d.ts @@ -1,9 +1,25 @@ import type { HostChatActionSubscribeItem, HostRendererActionSubscribeItem, ProductRendererRenderRequest, RendererNode, WireProvider } from "@parity/truapi"; import type { CoreAdmin, CoreStorageKey, ProductExecutionKind } from "./generated/host-callbacks.js"; export * from "./generated/host-callbacks.js"; -export type { JsonRpcConnection as PlatformJsonRpcConnection, } from "./generated/host-callbacks.js"; +export type { JsonRpcConnection as PlatformJsonRpcConnection } from "./generated/host-callbacks.js"; /** Encode a typed core-storage slot for hosts that need an opaque backing key. */ export declare function encodeCoreStorageKey(key: CoreStorageKey): Uint8Array; +/** Authenticated, ready native Chat peer. Host-private; never a product directory. */ +export interface NativeChatContact { + /** Canonical lowercase 0x-prefixed People identity account. */ + peerIdentity: string; + /** Verified roster name, absent when authorized products disagree. */ + username?: string; +} +/** Current signing wallet's authenticated native Chat contacts, restored from storage. */ +export interface NativeChatContactsSnapshot { + /** Canonical lowercase 0x-prefixed root wallet public key. */ + walletPublicKey: string; + /** Canonical lowercase 0x-prefixed People chain genesis hash. */ + genesisHash: string; + /** Deterministically ordered, deduplicated ready peers. */ + contacts: NativeChatContact[]; +} /** * Async-or-sync return. Synchronous hosts (e.g. the dotli main-thread * shell hitting localStorage) can return a plain value; the WASM bridge @@ -14,11 +30,15 @@ export type Awaitable = T | Promise; * Open a JSON-RPC connection for `genesisHash`. The wasm bridge passes * `onResponse` so the host can push JSON-RPC replies back asynchronously. * Returning `null` (or throwing) tells the core no provider is available. + * `onClosed`, when supplied, is called when the remote response stream ends + * or fails. Local `close()` is idempotent and does not call it. */ -export type ChainConnect = (genesisHash: string, onResponse: (json: string) => void) => Awaitable; +export type ChainConnect = (genesisHash: string, onResponse: (json: string) => void, onClosed?: () => void) => Awaitable; +/** Open only a host-allowlisted HOP endpoint for this Bulletin chain. */ +export type HopConnect = (bulletinGenesisHash: string, endpoint: string, onResponse: (json: string) => void, onClosed?: () => void) => Awaitable; /** - * Per-connection handle returned by `chainConnect`. `send` forwards a - * SCALE-encoded JSON-RPC request; `close` tears the connection down. + * Per-connection handle returned by `chainConnect` or `hopConnect`. `send` + * forwards a JSON-RPC request string; `close` tears the connection down. */ export interface ChainConnection { send(request: string): void; diff --git a/vendor/truapi-host/dist/testing/create-mock-client.cjs b/vendor/truapi-host/dist/testing/create-mock-client.cjs index 547f478e3..078fefb8f 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, CoreStorageKey, CreateProofReview, CreateTransactionReview, DevicePermissionStatus, HostChainEntry, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, IdentityDisclosureReview, LoginFailureKind, PermissionAuthorizationRequest, PermissionAuthorizationStatus, PermissionDecision, PreimageSubmitReview, ProductContext, ProductExecutionKind, ProductSubtreeReview, ResourceAllocationReview, SessionUiInfo, SignPayloadReview, SignRawReview, SignVrfReview, StatementStoreProductSignReview, UserConfirmationReview; +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 init_host_callbacks = __esm({ "dist/generated/host-callbacks.js"() { "use strict"; @@ -556,7 +556,8 @@ var init_host_callbacks = __esm({ AccountAccessReview = S.lazy(() => S.Struct({ requestingProductId: S.str, targetProductId: S.str })); 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 })); - 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 }) })); + 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) }) })); 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")); @@ -567,7 +568,19 @@ var init_host_callbacks = __esm({ HostContactPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ account: 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")); - PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: import_truapi3.HostDevicePermissionRequest, Remote: import_truapi3.RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }) })); + 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) })); + NativeChatFileExportRequest = S.lazy(() => S.Struct({ productId: S.str, peerIdentity: S.Bytes(32), peerUsername: S.Option(S.str), metadata: import_truapi3.HostNativeChatAttachmentMetadata })); + NativeChatFilePickRequest = S.lazy(() => S.Struct({ productId: S.str, peerIdentity: S.Bytes(32), peerUsername: S.Option(S.str), maxFiles: S.u32 })); + NativeChatPickedFile = S.lazy(() => S.Struct({ sourceId: S.str, metadata: import_truapi3.HostNativeChatAttachmentMetadata })); + NativeCoinageFailure = S.lazy(() => S.Status("Unavailable", "InvalidRequest", "InvalidSource", "OperationConflict", "OperationNotFound", "InsufficientBalance", "UserRejected")); + NativeCoinageMemo = S.lazy(() => S.Struct({ secretKeys: S.Vector(S.Bytes()), totalValueRaw: S.str })); + NativeCoinageOperation = S.lazy(() => S.TaggedUnion({ Denomination: S._void, PreparePayment: S.Struct({ intent: NativeCoinagePaymentIntent }), CommitHandoff: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), Views: S.Struct({ productId: S.str }), PendingHandoffs: S.Struct({ productId: S.str, acceptedOperations: S.Vector(S.Bytes(32)) }), ReadHandoff: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), NoteDelivery: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), Reconcile: S._void, TopUp: S.Struct({ productId: S.str, operationId: S.Bytes(32), minimumAmountRaw: S.str, secretKeys: S.Vector(S.Bytes()) }) })); + NativeCoinagePaymentIntent = S.lazy(() => S.Struct({ operationId: S.Bytes(32), productId: S.str, requestId: S.str, peerIdentity: S.Bytes(32), recipientUsername: S.Option(S.str), amountCents: S.u64 })); + NativeCoinageRequest = S.lazy(() => S.Struct({ scope: NativeCoinageScope, operation: NativeCoinageOperation })); + 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) }) })); PermissionAuthorizationStatus = S.lazy(() => S.Status("NotDetermined", "Denied", "Authorized")); PermissionDecision = S.lazy(() => S.Status("AllowOnce", "AllowAlways", "Deny")); PreimageSubmitReview = S.lazy(() => S.Struct({ size: S.u64 })); @@ -580,7 +593,7 @@ var init_host_callbacks = __esm({ 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 })); + 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 })); } }); @@ -625,51 +638,158 @@ function toAsyncIterator(stream) { } return asyncIterator; } -function pumpIterator(iterator, onItem, label, onError) { +function pumpIterator(iterator, onItem, label, onError, onComplete) { let stopped = false; void (async () => { try { while (!stopped) { const next = await iterator.next(); - if (next.done) + if (stopped || next.done) return; onItem(next.value); } } catch (err2) { - console.error(`[truapi host callbacks] ${label} failed:`, err2); - onError?.({ reason: errorMessage(err2) }); + if (!stopped) { + console.error(`[truapi host callbacks] ${label} failed`); + onError?.({ reason: errorMessage(err2) }); + } + } finally { + if (!stopped) + onComplete?.(); } })(); return () => { + if (stopped) + return; stopped = true; - void iterator.return?.(); + try { + void Promise.resolve(iterator.return?.()).catch(() => { + console.error(`[truapi host callbacks] ${label} cleanup failed`); + }); + } catch { + console.error(`[truapi host callbacks] ${label} cleanup failed`); + } }; } function driveResultStream(stream, sendItem, sendError) { return pumpIterator(toAsyncIterator(stream), (value) => sendItem(unwrapStreamResult(value)), "subscription", sendError); } function chainConnectAdapter(host) { - return async (genesisHash, onResponse) => { - const connection = await host.connect((0, import_scale.hexToBytes)(genesisHash)); - const iterator = connection.responses()[Symbol.asyncIterator](); - const stopResponses = pumpIterator(iterator, onResponse, "chain responses"); - return { - send(request) { + return async (genesisHash, onResponse, onClosed) => rpcConnectionAdapter(await host.connect((0, import_scale.hexToBytes)(genesisHash)), onResponse, onClosed); +} +function coinageWalletHostAdapter(host) { + if (host === void 0) + return void 0; + let nativeCoinage; + try { + nativeCoinage = host.nativeCoinage.bind(host); + } catch { + throw new Error("Native Coinage wallet callback is unavailable"); + } + return { + async nativeCoinage(request) { + try { + return await nativeCoinage(request); + } catch { + throw new Error("Native Coinage wallet operation failed"); + } + } + }; +} +function hopConnectAdapter(host) { + return async (genesisHash, endpoint, onResponse, onClosed) => { + const genesis = (0, import_scale.hexToBytes)(genesisHash); + const allowed = await host.allowedHopEndpoints(genesis); + if (!allowed.includes(endpoint) || !endpoint.startsWith("wss://") || /[\s\u0000-\u001f\u007f-\u009f#\\]/u.test(endpoint) || endpoint.slice(6).split(/[/?]/u, 1)[0].includes("@")) { + throw new Error("HOP endpoint is not an allowed secure WebSocket URL"); + } + const url = new URL(endpoint); + if (!url.hostname || url.username || url.password || url.hash) { + throw new Error("HOP endpoint is not an allowed secure WebSocket URL"); + } + return rpcConnectionAdapter(await host.connectHop(genesis, endpoint), onResponse, onClosed); + }; +} +function rpcConnectionAdapter(connection, onResponse, onClosed) { + let closed = false; + let stopResponses; + const close = (notify) => { + if (closed) + return; + closed = true; + stopResponses?.(); + try { + connection.close(); + } finally { + if (notify) + onClosed?.(); + } + }; + try { + stopResponses = pumpIterator(connection.responses()[Symbol.asyncIterator](), onResponse, "JSON-RPC responses", void 0, () => { + try { + close(true); + } catch { + console.error("[truapi host callbacks] JSON-RPC close failed"); + } + }); + if (closed) + stopResponses(); + } catch (err2) { + close(false); + throw err2; + } + return { + send(request) { + if (closed) + throw new Error("JSON-RPC connection is closed"); + try { connection.send(request); - }, - close() { - stopResponses(); - connection.close(); + } catch (err2) { + close(true); + throw err2; } - }; + }, + close: () => close(false) }; } -var import_scale; +var import_scale, unavailableHopProvider, unavailableNativeChatFilesHost; var init_adapter_support = __esm({ "dist/adapter-support.js"() { "use strict"; import_scale = require("@parity/truapi/scale"); init_error(); + unavailableHopProvider = { + async allowedHopEndpoints() { + return []; + }, + async connectHop() { + throw new Error("HOP provider is unavailable"); + } + }; + unavailableNativeChatFilesHost = { + async pickChatFiles() { + throw new Error("Native Chat files are unavailable"); + }, + async readChatFile() { + throw new Error("Native Chat files are unavailable"); + }, + async releaseChatFile() { + throw new Error("Native Chat files are unavailable"); + }, + async beginChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async writeChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async finishChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async cancelChatFileExport() { + throw new Error("Native Chat files are unavailable"); + } + }; } }); @@ -680,9 +800,13 @@ __export(host_callbacks_adapter_exports, { }); function createWasmRawCallbacks(callbacks) { const chat = callbacks.chat; + const coinageWallet = coinageWalletHostAdapter(callbacks.coinageWallet); const contacts = callbacks.contacts; + const identityBackend = callbacks.identityBackend; const permissionStatus = callbacks.permissionStatus; const pocket = callbacks.pocket; + const hop = callbacks.hop ?? unavailableHopProvider; + const nativeChatFiles = callbacks.nativeChatFiles ?? unavailableNativeChatFilesHost; return { authStateChanged: async (state) => await callbacks.auth.authStateChanged(AuthState.dec(state)), chainConnect: chainConnectAdapter(callbacks.chain), @@ -692,6 +816,9 @@ function createWasmRawCallbacks(callbacks) { postChatMessage: async (product, request) => import_truapi4.HostChatPostMessageResponse.enc(await chat.postChatMessage(ProductContext.dec(product), import_truapi4.HostChatPostMessageRequest.dec(request))), subscribeChatRooms: (product, sendItem, sendError) => driveResultStream(chat.subscribeChatRooms(ProductContext.dec(product)), (item) => sendItem(import_truapi4.HostChatListSubscribeItem.enc(item)), sendError) } : {}, + ...coinageWallet ? { + nativeCoinage: async (request) => NativeCoinageResponse.enc(await coinageWallet.nativeCoinage(NativeCoinageRequest.dec(request))) + } : {}, ...contacts ? { contacts: async (lookup) => HostContactMatches.enc(await contacts.contacts(HostContactLookup.dec(lookup))), pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))) @@ -701,8 +828,20 @@ function createWasmRawCallbacks(callbacks) { clearCoreStorage: async (key) => await callbacks.coreStorage.clearCoreStorage(CoreStorageKey.dec(key)), featureSupported: async (request) => import_truapi4.HostFeatureSupportedResponse.enc(await callbacks.features.featureSupported(import_truapi4.HostFeatureSupportedRequest.dec(request))), supportedChains: async () => HostChainSet.enc(await callbacks.features.supportedChains()), + allowedHopEndpoints: async (bulletinGenesisHash) => allowedHopEndpointsResultCodec.enc(await hop.allowedHopEndpoints(bulletinGenesisHash)), + hopConnect: hopConnectAdapter(hop), + ...identityBackend ? { + identityUsernameCandidates: async (username, peopleChainGenesisHash) => identityUsernameCandidatesResultCodec.enc(await identityBackend.identityUsernameCandidates(username, peopleChainGenesisHash)) + } : {}, subscribeLocale: (sendItem, sendError) => driveResultStream(callbacks.locale.subscribeLocale(), (item) => sendItem(import_truapi4.HostLocaleSubscribeItem.enc(item)), sendError), localizeTimestamps: async (request) => import_truapi4.HostLocaleLocalizeTimestampsResponse.enc(await callbacks.locale.localizeTimestamps(import_truapi4.HostLocaleLocalizeTimestampsRequest.dec(request))), + pickChatFiles: async (request) => pickChatFilesResultCodec.enc(await nativeChatFiles.pickChatFiles(NativeChatFilePickRequest.dec(request))), + readChatFile: async (sourceId, offset, length) => await nativeChatFiles.readChatFile(sourceId, offset, length), + releaseChatFile: async (sourceId) => await nativeChatFiles.releaseChatFile(sourceId), + beginChatFileExport: async (request) => await nativeChatFiles.beginChatFileExport(NativeChatFileExportRequest.dec(request)), + writeChatFileExport: async (exportId, offset, data) => await nativeChatFiles.writeChatFileExport(exportId, offset, data), + finishChatFileExport: async (exportId) => await nativeChatFiles.finishChatFileExport(exportId), + cancelChatFileExport: async (exportId) => await nativeChatFiles.cancelChatFileExport(exportId), navigateTo: async (url) => await callbacks.navigation.navigateTo(url), pushNotification: async (notification) => import_truapi4.HostPushNotificationResponse.enc(await callbacks.notifications.pushNotification(import_truapi4.HostPushNotificationRequest.dec(notification))), cancelNotification: async (id) => await callbacks.notifications.cancelNotification(id), @@ -727,13 +866,17 @@ function createWasmRawCallbacks(callbacks) { confirmUserAction: async (review) => await callbacks.userConfirmation.confirmUserAction(UserConfirmationReview.dec(review)) }; } -var import_truapi4; +var S2, import_truapi4, allowedHopEndpointsResultCodec, identityUsernameCandidatesResultCodec, pickChatFilesResultCodec; var init_host_callbacks_adapter = __esm({ "dist/generated/host-callbacks-adapter.js"() { "use strict"; + S2 = __toESM(require("@parity/truapi/scale"), 1); import_truapi4 = require("@parity/truapi"); init_host_callbacks(); init_adapter_support(); + allowedHopEndpointsResultCodec = S2.Vector(S2.str); + identityUsernameCandidatesResultCodec = S2.Vector(S2.Bytes(32)); + pickChatFilesResultCodec = S2.Vector(NativeChatPickedFile); } }); diff --git a/vendor/truapi-host/dist/testing/host-page.cjs b/vendor/truapi-host/dist/testing/host-page.cjs index 26761cde2..77b55bf51 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, CoreStorageKey, CreateProofReview, CreateTransactionReview, DevicePermissionStatus, HostChainEntry, HostChainSet, HostContactLookup, HostContactMatches, HostContactPick, IdentityDisclosureReview, LoginFailureKind, PermissionAuthorizationRequest, PermissionAuthorizationStatus, PermissionDecision, PreimageSubmitReview, ProductContext, ProductExecutionKind, ProductSubtreeReview, ResourceAllocationReview, SessionUiInfo, SignPayloadReview, SignRawReview, SignVrfReview, StatementStoreProductSignReview, UserConfirmationReview; +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 init_host_callbacks = __esm({ "dist/generated/host-callbacks.js"() { "use strict"; @@ -53,7 +53,8 @@ var init_host_callbacks = __esm({ AccountAccessReview = S.lazy(() => S.Struct({ requestingProductId: S.str, targetProductId: S.str })); 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 })); - 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 }) })); + 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) }) })); 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")); @@ -64,7 +65,19 @@ var init_host_callbacks = __esm({ HostContactPick = S.lazy(() => S.TaggedUnion({ Picked: S.Struct({ account: 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")); - PermissionAuthorizationRequest = S.lazy(() => S.TaggedUnion({ Device: import_truapi.HostDevicePermissionRequest, Remote: import_truapi.RemotePermissionRequest, IdentityDisclosure: S._void, AccountAccess: S.Struct({ targetProductId: S.str }) })); + 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) })); + NativeChatFileExportRequest = S.lazy(() => S.Struct({ productId: S.str, peerIdentity: S.Bytes(32), peerUsername: S.Option(S.str), metadata: import_truapi.HostNativeChatAttachmentMetadata })); + NativeChatFilePickRequest = S.lazy(() => S.Struct({ productId: S.str, peerIdentity: S.Bytes(32), peerUsername: S.Option(S.str), maxFiles: S.u32 })); + NativeChatPickedFile = S.lazy(() => S.Struct({ sourceId: S.str, metadata: import_truapi.HostNativeChatAttachmentMetadata })); + NativeCoinageFailure = S.lazy(() => S.Status("Unavailable", "InvalidRequest", "InvalidSource", "OperationConflict", "OperationNotFound", "InsufficientBalance", "UserRejected")); + NativeCoinageMemo = S.lazy(() => S.Struct({ secretKeys: S.Vector(S.Bytes()), totalValueRaw: S.str })); + NativeCoinageOperation = S.lazy(() => S.TaggedUnion({ Denomination: S._void, PreparePayment: S.Struct({ intent: NativeCoinagePaymentIntent }), CommitHandoff: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), Views: S.Struct({ productId: S.str }), PendingHandoffs: S.Struct({ productId: S.str, acceptedOperations: S.Vector(S.Bytes(32)) }), ReadHandoff: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), NoteDelivery: S.Struct({ productId: S.str, operationId: S.Bytes(32) }), Reconcile: S._void, TopUp: S.Struct({ productId: S.str, operationId: S.Bytes(32), minimumAmountRaw: S.str, secretKeys: S.Vector(S.Bytes()) }) })); + NativeCoinagePaymentIntent = S.lazy(() => S.Struct({ operationId: S.Bytes(32), productId: S.str, requestId: S.str, peerIdentity: S.Bytes(32), recipientUsername: S.Option(S.str), amountCents: S.u64 })); + NativeCoinageRequest = S.lazy(() => S.Struct({ scope: NativeCoinageScope, operation: NativeCoinageOperation })); + 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) }) })); PermissionAuthorizationStatus = S.lazy(() => S.Status("NotDetermined", "Denied", "Authorized")); PermissionDecision = S.lazy(() => S.Status("AllowOnce", "AllowAlways", "Deny")); PreimageSubmitReview = S.lazy(() => S.Struct({ size: S.u64 })); @@ -77,7 +90,7 @@ var init_host_callbacks = __esm({ 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 })); + 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 })); } }); @@ -125,51 +138,158 @@ function toAsyncIterator(stream) { } return asyncIterator; } -function pumpIterator(iterator, onItem, label, onError) { +function pumpIterator(iterator, onItem, label, onError, onComplete) { let stopped = false; void (async () => { try { while (!stopped) { const next = await iterator.next(); - if (next.done) + if (stopped || next.done) return; onItem(next.value); } } catch (err2) { - console.error(`[truapi host callbacks] ${label} failed:`, err2); - onError?.({ reason: errorMessage(err2) }); + if (!stopped) { + console.error(`[truapi host callbacks] ${label} failed`); + onError?.({ reason: errorMessage(err2) }); + } + } finally { + if (!stopped) + onComplete?.(); } })(); return () => { + if (stopped) + return; stopped = true; - void iterator.return?.(); + try { + void Promise.resolve(iterator.return?.()).catch(() => { + console.error(`[truapi host callbacks] ${label} cleanup failed`); + }); + } catch { + console.error(`[truapi host callbacks] ${label} cleanup failed`); + } }; } function driveResultStream(stream, sendItem, sendError) { return pumpIterator(toAsyncIterator(stream), (value) => sendItem(unwrapStreamResult(value)), "subscription", sendError); } function chainConnectAdapter(host) { - return async (genesisHash, onResponse) => { - const connection = await host.connect((0, import_scale.hexToBytes)(genesisHash)); - const iterator = connection.responses()[Symbol.asyncIterator](); - const stopResponses = pumpIterator(iterator, onResponse, "chain responses"); - return { - send(request) { + return async (genesisHash, onResponse, onClosed) => rpcConnectionAdapter(await host.connect((0, import_scale.hexToBytes)(genesisHash)), onResponse, onClosed); +} +function coinageWalletHostAdapter(host) { + if (host === void 0) + return void 0; + let nativeCoinage; + try { + nativeCoinage = host.nativeCoinage.bind(host); + } catch { + throw new Error("Native Coinage wallet callback is unavailable"); + } + return { + async nativeCoinage(request) { + try { + return await nativeCoinage(request); + } catch { + throw new Error("Native Coinage wallet operation failed"); + } + } + }; +} +function hopConnectAdapter(host) { + return async (genesisHash, endpoint, onResponse, onClosed) => { + const genesis = (0, import_scale.hexToBytes)(genesisHash); + const allowed = await host.allowedHopEndpoints(genesis); + if (!allowed.includes(endpoint) || !endpoint.startsWith("wss://") || /[\s\u0000-\u001f\u007f-\u009f#\\]/u.test(endpoint) || endpoint.slice(6).split(/[/?]/u, 1)[0].includes("@")) { + throw new Error("HOP endpoint is not an allowed secure WebSocket URL"); + } + const url = new URL(endpoint); + if (!url.hostname || url.username || url.password || url.hash) { + throw new Error("HOP endpoint is not an allowed secure WebSocket URL"); + } + return rpcConnectionAdapter(await host.connectHop(genesis, endpoint), onResponse, onClosed); + }; +} +function rpcConnectionAdapter(connection, onResponse, onClosed) { + let closed = false; + let stopResponses; + const close = (notify) => { + if (closed) + return; + closed = true; + stopResponses?.(); + try { + connection.close(); + } finally { + if (notify) + onClosed?.(); + } + }; + try { + stopResponses = pumpIterator(connection.responses()[Symbol.asyncIterator](), onResponse, "JSON-RPC responses", void 0, () => { + try { + close(true); + } catch { + console.error("[truapi host callbacks] JSON-RPC close failed"); + } + }); + if (closed) + stopResponses(); + } catch (err2) { + close(false); + throw err2; + } + return { + send(request) { + if (closed) + throw new Error("JSON-RPC connection is closed"); + try { connection.send(request); - }, - close() { - stopResponses(); - connection.close(); + } catch (err2) { + close(true); + throw err2; } - }; + }, + close: () => close(false) }; } -var import_scale; +var import_scale, unavailableHopProvider, unavailableNativeChatFilesHost; var init_adapter_support = __esm({ "dist/adapter-support.js"() { "use strict"; import_scale = require("@parity/truapi/scale"); init_error(); + unavailableHopProvider = { + async allowedHopEndpoints() { + return []; + }, + async connectHop() { + throw new Error("HOP provider is unavailable"); + } + }; + unavailableNativeChatFilesHost = { + async pickChatFiles() { + throw new Error("Native Chat files are unavailable"); + }, + async readChatFile() { + throw new Error("Native Chat files are unavailable"); + }, + async releaseChatFile() { + throw new Error("Native Chat files are unavailable"); + }, + async beginChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async writeChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async finishChatFileExport() { + throw new Error("Native Chat files are unavailable"); + }, + async cancelChatFileExport() { + throw new Error("Native Chat files are unavailable"); + } + }; } }); @@ -180,9 +300,13 @@ __export(host_callbacks_adapter_exports, { }); function createWasmRawCallbacks(callbacks) { const chat = callbacks.chat; + const coinageWallet = coinageWalletHostAdapter(callbacks.coinageWallet); const contacts = callbacks.contacts; + const identityBackend = callbacks.identityBackend; const permissionStatus = callbacks.permissionStatus; const pocket = callbacks.pocket; + const hop = callbacks.hop ?? unavailableHopProvider; + const nativeChatFiles = callbacks.nativeChatFiles ?? unavailableNativeChatFilesHost; return { authStateChanged: async (state) => await callbacks.auth.authStateChanged(AuthState.dec(state)), chainConnect: chainConnectAdapter(callbacks.chain), @@ -192,6 +316,9 @@ function createWasmRawCallbacks(callbacks) { postChatMessage: async (product, request) => import_truapi2.HostChatPostMessageResponse.enc(await chat.postChatMessage(ProductContext.dec(product), import_truapi2.HostChatPostMessageRequest.dec(request))), subscribeChatRooms: (product, sendItem, sendError) => driveResultStream(chat.subscribeChatRooms(ProductContext.dec(product)), (item) => sendItem(import_truapi2.HostChatListSubscribeItem.enc(item)), sendError) } : {}, + ...coinageWallet ? { + nativeCoinage: async (request) => NativeCoinageResponse.enc(await coinageWallet.nativeCoinage(NativeCoinageRequest.dec(request))) + } : {}, ...contacts ? { contacts: async (lookup) => HostContactMatches.enc(await contacts.contacts(HostContactLookup.dec(lookup))), pickContact: async (product) => HostContactPick.enc(await contacts.pickContact(ProductContext.dec(product))) @@ -201,8 +328,20 @@ function createWasmRawCallbacks(callbacks) { clearCoreStorage: async (key) => await callbacks.coreStorage.clearCoreStorage(CoreStorageKey.dec(key)), featureSupported: async (request) => import_truapi2.HostFeatureSupportedResponse.enc(await callbacks.features.featureSupported(import_truapi2.HostFeatureSupportedRequest.dec(request))), supportedChains: async () => HostChainSet.enc(await callbacks.features.supportedChains()), + allowedHopEndpoints: async (bulletinGenesisHash) => allowedHopEndpointsResultCodec.enc(await hop.allowedHopEndpoints(bulletinGenesisHash)), + hopConnect: hopConnectAdapter(hop), + ...identityBackend ? { + identityUsernameCandidates: async (username, peopleChainGenesisHash) => identityUsernameCandidatesResultCodec.enc(await identityBackend.identityUsernameCandidates(username, peopleChainGenesisHash)) + } : {}, subscribeLocale: (sendItem, sendError) => driveResultStream(callbacks.locale.subscribeLocale(), (item) => sendItem(import_truapi2.HostLocaleSubscribeItem.enc(item)), sendError), localizeTimestamps: async (request) => import_truapi2.HostLocaleLocalizeTimestampsResponse.enc(await callbacks.locale.localizeTimestamps(import_truapi2.HostLocaleLocalizeTimestampsRequest.dec(request))), + pickChatFiles: async (request) => pickChatFilesResultCodec.enc(await nativeChatFiles.pickChatFiles(NativeChatFilePickRequest.dec(request))), + readChatFile: async (sourceId, offset, length) => await nativeChatFiles.readChatFile(sourceId, offset, length), + releaseChatFile: async (sourceId) => await nativeChatFiles.releaseChatFile(sourceId), + beginChatFileExport: async (request) => await nativeChatFiles.beginChatFileExport(NativeChatFileExportRequest.dec(request)), + writeChatFileExport: async (exportId, offset, data) => await nativeChatFiles.writeChatFileExport(exportId, offset, data), + finishChatFileExport: async (exportId) => await nativeChatFiles.finishChatFileExport(exportId), + cancelChatFileExport: async (exportId) => await nativeChatFiles.cancelChatFileExport(exportId), navigateTo: async (url) => await callbacks.navigation.navigateTo(url), pushNotification: async (notification) => import_truapi2.HostPushNotificationResponse.enc(await callbacks.notifications.pushNotification(import_truapi2.HostPushNotificationRequest.dec(notification))), cancelNotification: async (id) => await callbacks.notifications.cancelNotification(id), @@ -227,13 +366,17 @@ function createWasmRawCallbacks(callbacks) { confirmUserAction: async (review) => await callbacks.userConfirmation.confirmUserAction(UserConfirmationReview.dec(review)) }; } -var import_truapi2; +var S2, import_truapi2, allowedHopEndpointsResultCodec, identityUsernameCandidatesResultCodec, pickChatFilesResultCodec; var init_host_callbacks_adapter = __esm({ "dist/generated/host-callbacks-adapter.js"() { "use strict"; + S2 = __toESM(require("@parity/truapi/scale"), 1); import_truapi2 = require("@parity/truapi"); init_host_callbacks(); init_adapter_support(); + allowedHopEndpointsResultCodec = S2.Vector(S2.str); + identityUsernameCandidatesResultCodec = S2.Vector(S2.Bytes(32)); + pickChatFilesResultCodec = S2.Vector(NativeChatPickedFile); } }); @@ -837,6 +980,10 @@ init_host_callbacks(); init_host_callbacks_adapter(); // dist/worker-protocol.js +var MAX_JSON_RPC_CONNECTIONS = 64; +var COINAGE_WALLET_CALLBACKS = { + nativeCoinage: true +}; function isLoopbackWsUrl(url) { try { const u = new URL(url); @@ -850,7 +997,7 @@ function isLoopbackWsUrl(url) { } // dist/web/create-worker-host-runtime.js -var import_scale2 = require("@parity/truapi/scale"); +var import_scale3 = require("@parity/truapi/scale"); // dist/generated/worker-callbacks.js function startRawSubscription(callbacks, name, payload, sendItem, sendError) { @@ -889,6 +1036,741 @@ function startRawSubscription(callbacks, name, payload, sendItem, sendError) { // dist/web/create-worker-host-runtime.js init_error(); +// dist/web/native-chat-files.js +var import_scale2 = require("@parity/truapi/scale"); + +// dist/web/native-chat-media.js +var HEADER_LIMIT = 65536; +var VIDEO_TIMEOUT_MS = 5e3; +var U32_MAX = 4294967295; +var MP4_BRANDS = [ + "isom", + "iso2", + "iso3", + "iso4", + "iso5", + "iso6", + "mp41", + "mp42", + "avc1", + "M4V ", + "M4VH", + "M4VP" +]; +var PNG_DEPTHS = { + 0: [1, 2, 4, 8, 16], + 2: [8, 16], + 3: [1, 2, 4, 8], + 4: [8, 16], + 6: [8, 16] +}; +function matches(bytes2, offset, signature) { + if (offset + signature.length > bytes2.length) + return false; + for (let i = 0; i < signature.length; i++) { + if (bytes2[offset + i] !== signature.charCodeAt(i)) + return false; + } + return true; +} +function imageHeader(bytes2, fileSize) { + const view = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength); + if (bytes2.length >= 33 && matches(bytes2, 0, "\x89PNG\r\n\n") && view.getUint32(8) === 13 && matches(bytes2, 12, "IHDR")) { + const width = view.getUint32(16); + const height = view.getUint32(20); + if (width > 0 && height > 0 && width <= 2147483647 && height <= 2147483647 && PNG_DEPTHS[bytes2[25]]?.includes(bytes2[24]) && bytes2[26] === 0 && bytes2[27] === 0 && bytes2[28] <= 1) { + return { mimeType: "image/png", width, height }; + } + return void 0; + } + if (bytes2.length >= 13 && (matches(bytes2, 0, "GIF87a") || matches(bytes2, 0, "GIF89a"))) { + const width = view.getUint16(6, true); + const height = view.getUint16(8, true); + if (width && height) + return { mimeType: "image/gif", width, height }; + return void 0; + } + if (bytes2.length >= 4 && bytes2[0] === 255 && bytes2[1] === 216) { + let offset = 2; + while (offset + 4 <= bytes2.length) { + if (bytes2[offset++] !== 255) + return void 0; + while (offset < bytes2.length && bytes2[offset] === 255) + offset++; + const marker = bytes2[offset++]; + if (marker === void 0 || marker === 218 || marker === 217 || marker === 0) + return void 0; + if (marker === 1 || marker >= 208 && marker <= 215) + continue; + if (offset + 2 > bytes2.length) + return void 0; + const length = view.getUint16(offset); + if (length < 2 || offset + length > bytes2.length) + return void 0; + if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) { + if (length < 8) + return void 0; + const height = view.getUint16(offset + 3); + const width = view.getUint16(offset + 5); + const components = bytes2[offset + 7]; + if (width && height && components > 0 && length === 8 + 3 * components) { + return { mimeType: "image/jpeg", width, height }; + } + return void 0; + } + offset += length; + } + return void 0; + } + if (bytes2.length >= 30 && matches(bytes2, 0, "RIFF") && matches(bytes2, 8, "WEBP") && view.getUint32(4, true) + 8 === fileSize) { + const chunkSize = view.getUint32(16, true); + if (20 + chunkSize + (chunkSize & 1) > fileSize) + return void 0; + if (matches(bytes2, 12, "VP8X") && chunkSize === 10) { + const width = 1 + bytes2[24] + (bytes2[25] << 8) + (bytes2[26] << 16); + const height = 1 + bytes2[27] + (bytes2[28] << 8) + (bytes2[29] << 16); + return { mimeType: "image/webp", width, height }; + } + if (matches(bytes2, 12, "VP8 ") && chunkSize >= 10 && (bytes2[20] & 1) === 0 && matches(bytes2, 23, "\x9D*")) { + const width = view.getUint16(26, true) & 16383; + const height = view.getUint16(28, true) & 16383; + if (width && height) + return { mimeType: "image/webp", width, height }; + } + } + if (bytes2.length >= 25 && matches(bytes2, 0, "RIFF") && matches(bytes2, 8, "WEBP") && matches(bytes2, 12, "VP8L") && view.getUint32(4, true) + 8 === fileSize) { + const chunkSize = view.getUint32(16, true); + if (chunkSize >= 5 && 20 + chunkSize + (chunkSize & 1) <= fileSize && bytes2[20] === 47 && bytes2[24] >> 5 === 0) { + const width = 1 + bytes2[21] + ((bytes2[22] & 63) << 8); + const height = 1 + (bytes2[22] >> 6) + (bytes2[23] << 2) + ((bytes2[24] & 15) << 10); + return { mimeType: "image/webp", width, height }; + } + } + return void 0; +} +function ebmlInteger(bytes2, offset, id) { + const first = bytes2[offset]; + if (first === void 0 || first === 0) + return void 0; + let marker = 128; + let length = 1; + while ((first & marker) === 0) { + marker >>= 1; + length++; + } + if (length > (id ? 4 : 8) || offset + length > bytes2.length) + return void 0; + let value = id ? first : first & marker - 1; + for (let i = 1; i < length; i++) + value = value * 256 + bytes2[offset + i]; + if (!Number.isSafeInteger(value) || !id && value === 2 ** (7 * length) - 1) + return void 0; + return { value, next: offset + length }; +} +function videoMime(bytes2, fileSize) { + if (bytes2.length >= 16 && matches(bytes2, 4, "ftyp")) { + const size = new DataView(bytes2.buffer, bytes2.byteOffset, bytes2.byteLength).getUint32(0); + if (size < 16 || size > bytes2.length || size > fileSize || size % 4 !== 0) + return void 0; + if (matches(bytes2, 8, "qt ")) + return "video/quicktime"; + for (const brand of MP4_BRANDS) { + if (matches(bytes2, 8, brand)) + return "video/mp4"; + } + return void 0; + } + if (!matches(bytes2, 0, "E\xDF\xA3")) + return void 0; + const header = ebmlInteger(bytes2, 4, false); + if (!header || header.value > bytes2.length - header.next) + return void 0; + const end = header.next + header.value; + if (!matches(bytes2, end, "S\x80g")) + return void 0; + let offset = header.next; + let webm = false; + while (offset < end) { + const id = ebmlInteger(bytes2, offset, true); + if (!id || id.next > end) + return void 0; + const size = ebmlInteger(bytes2, id.next, false); + if (!size || size.next > end || size.value > end - size.next) + return void 0; + if (id.value === 17026) { + if (webm || size.value !== 4 || !matches(bytes2, size.next, "webm")) + return void 0; + webm = true; + } + offset = size.next + size.value; + } + return webm ? "video/webm" : void 0; +} +async function inspectNativeChatFileMetadata(blob, signal) { + if (!Number.isInteger(blob.size) || blob.size < 0 || blob.size > U32_MAX) + throw new Error("Chat file size exceeds the supported range"); + const fallback = { + mimeType: "application/octet-stream", + sizeBytes: blob.size, + kind: { tag: "File" } + }; + if (signal?.aborted) + return fallback; + const bytes2 = new Uint8Array(await blob.slice(0, HEADER_LIMIT).arrayBuffer()); + if (signal?.aborted) + return fallback; + const image = imageHeader(bytes2, blob.size); + if (image) { + return { + mimeType: image.mimeType, + sizeBytes: blob.size, + kind: { + tag: "Image", + value: { + width: image.width, + height: image.height, + thumbnail: void 0 + } + } + }; + } + const mimeType = videoMime(bytes2, blob.size); + if (!mimeType || typeof document === "undefined") + return fallback; + let video; + let url; + try { + video = document.createElement("video"); + video.preload = "metadata"; + video.autoplay = false; + video.muted = true; + video.playsInline = true; + url = URL.createObjectURL(blob.slice(0, blob.size, mimeType)); + } catch { + return fallback; + } + return new Promise((resolve) => { + let settled = false; + const finish = (metadata) => { + if (settled) + return; + settled = true; + clearTimeout(timer); + signal?.removeEventListener("abort", abort); + video.onloadedmetadata = video.onerror = null; + try { + video.removeAttribute("src"); + video.load(); + } catch { + } finally { + URL.revokeObjectURL(url); + resolve(metadata); + } + }; + const abort = () => finish(fallback); + const timer = setTimeout(abort, VIDEO_TIMEOUT_MS); + signal?.addEventListener("abort", abort, { once: true }); + video.onerror = abort; + video.onloadedmetadata = () => { + const duration = video.duration; + if (!Number.isFinite(duration) || duration < 0 || duration > U32_MAX || video.videoWidth <= 0 || video.videoHeight <= 0) { + finish(fallback); + } else { + finish({ + mimeType, + sizeBytes: blob.size, + kind: { + tag: "Video", + value: { + durationSeconds: Math.floor(duration), + thumbnail: void 0 + } + } + }); + } + }; + if (signal?.aborted) { + abort(); + return; + } + try { + video.src = url; + video.load(); + } catch { + abort(); + } + }); +} +var IMAGE_EXTENSIONS = { + "image/png": "png", + "image/jpeg": "jpg", + "image/gif": "gif", + "image/webp": "webp" +}; +var VIDEO_EXTENSIONS = { + "video/mp4": "mp4", + "video/quicktime": "mov", + "video/webm": "webm" +}; +function nativeChatExportFilename(metadata) { + let extension = "bin"; + if (metadata.kind.tag === "Image") { + const { width, height } = metadata.kind.value; + if (Number.isInteger(width) && Number.isInteger(height) && width > 0 && height > 0 && width <= U32_MAX && height <= U32_MAX && Object.hasOwn(IMAGE_EXTENSIONS, metadata.mimeType)) { + extension = IMAGE_EXTENSIONS[metadata.mimeType]; + } + } else if (metadata.kind.tag === "Video") { + const { durationSeconds } = metadata.kind.value; + if (Number.isInteger(durationSeconds) && durationSeconds >= 0 && durationSeconds <= U32_MAX && Object.hasOwn(VIDEO_EXTENSIONS, metadata.mimeType)) { + extension = VIDEO_EXTENSIONS[metadata.mimeType]; + } + } + return `chat-attachment.${extension}`; +} + +// dist/web/native-chat-files.js +var MAX_FILE_SIZE = 4294967295; +var MAX_READ_SIZE = 2e6; +var DATABASE_NAME = "truapi-native-chat-files"; +var SOURCE_STORE = "sources"; +function checkedSize(size) { + if (!Number.isInteger(size) || size < 0 || size > MAX_FILE_SIZE) { + throw new Error("Chat file size exceeds the supported range"); + } +} +function safeLabel(value) { + return value.replace(/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/gu, " ").slice(0, 200); +} +function createBrowserNativeChatFilesHost(sourceStore) { + let disposed = false; + let database; + const dialogs = /* @__PURE__ */ new Set(); + const exports2 = /* @__PURE__ */ new Map(); + const mediaAbort = new AbortController(); + function available() { + if (disposed) + throw new Error("Native Chat files are unavailable"); + } + function openDatabase(cleanup = false) { + if (!cleanup) + available(); + if (!database) { + database = new Promise((resolve, reject) => { + if (!globalThis.indexedDB) { + reject(new Error("Durable Chat file storage is unavailable")); + return; + } + const request = indexedDB.open(DATABASE_NAME, 1); + let blocked = false; + request.onupgradeneeded = () => request.result.createObjectStore(SOURCE_STORE); + request.onerror = () => reject(new Error("Durable Chat file storage is unavailable")); + request.onblocked = () => { + blocked = true; + reject(new Error("Durable Chat file storage is blocked")); + }; + request.onsuccess = () => { + const db = request.result; + if (blocked || disposed && !cleanup) { + db.close(); + reject(new Error("Native Chat files are unavailable")); + return; + } + db.onversionchange = () => { + db.close(); + database = void 0; + }; + resolve(db); + }; + }).catch((error) => { + database = void 0; + throw error; + }); + } + return database; + } + async function store(mode, action, cleanup = false) { + const db = await openDatabase(cleanup); + if (!cleanup) + available(); + return new Promise((resolve, reject) => { + const transaction = db.transaction(SOURCE_STORE, mode, { + durability: "strict" + }); + const request = action(transaction.objectStore(SOURCE_STORE)); + transaction.oncomplete = () => { + if (disposed) { + db.close(); + database = void 0; + } + resolve(request.result); + }; + transaction.onerror = transaction.onabort = () => reject(new Error("Chat file storage failed")); + }); + } + function prompt(title, context, actionLabel, configure) { + available(); + if (typeof document === "undefined" || !document.body || window.top !== window) { + return Promise.reject(new Error("Trusted Chat file presentation is unavailable")); + } + return new Promise((resolve, reject) => { + const dialog = document.createElement("dialog"); + const heading = document.createElement("h2"); + heading.textContent = title; + const summary = document.createElement("p"); + summary.textContent = `Product: ${safeLabel(context.productId)} +Peer: ${safeLabel(context.peerUsername ?? "Chat contact")} +Identity: ${(0, import_scale2.bytesToHex)(context.peerIdentity)}`; + summary.style.whiteSpace = "pre-wrap"; + summary.style.overflowWrap = "anywhere"; + const content = document.createElement("div"); + const accept = document.createElement("button"); + accept.type = "button"; + accept.textContent = actionLabel; + const cancel = document.createElement("button"); + cancel.type = "button"; + cancel.textContent = "Cancel"; + dialog.setAttribute("aria-label", title); + dialog.style.maxWidth = "min(36rem, 90vw)"; + dialog.append(heading, summary, content, accept, cancel); + let settled = false; + let busy = false; + const close = () => { + dialogs.delete(abort); + dialog.close(); + dialog.remove(); + }; + const abort = () => { + if (settled) + return; + close(); + if (busy && disposed) + return; + settled = true; + resolve(void 0); + }; + dialogs.add(abort); + cancel.onclick = abort; + dialog.oncancel = (event) => { + event.preventDefault(); + if (!busy) + abort(); + }; + try { + const run = configure(content); + accept.onclick = () => { + if (busy || settled) + return; + busy = true; + accept.disabled = cancel.disabled = true; + let result; + try { + result = run(); + } catch (error) { + result = Promise.reject(error); + } + Promise.resolve(result).then((value) => { + if (!settled) { + settled = true; + close(); + resolve(value); + } + }, (error) => { + if (settled) + return; + busy = false; + if (error instanceof DOMException && error.name === "AbortError") { + abort(); + return; + } + settled = true; + close(); + reject(new Error("Chat file selection or export failed")); + }); + }; + document.body.append(dialog); + dialog.showModal(); + } catch { + settled = true; + close(); + reject(new Error("Trusted Chat file presentation is unavailable")); + } + }); + } + async function abortExport(id, entry) { + exports2.delete(id); + try { + await entry.writer.abort(); + } catch { + } + await entry.removePartial(); + } + function withExport(id, action) { + const entry = exports2.get(id); + if (!entry) + return Promise.reject(new Error("Chat file export is unavailable")); + const operation = entry.queue.then(async () => { + if (exports2.get(id) !== entry) + throw new Error("Chat file export is unavailable"); + await action(entry); + }); + entry.queue = operation.catch(() => { + }); + return operation; + } + const host = { + async pickChatFiles(request) { + checkedSize(request.maxFiles); + if (request.maxFiles === 0) + throw new Error("Chat file selection is unavailable"); + if (!sourceStore) + await openDatabase(); + const files = await prompt("Send Chat attachments", request, "Attach files", (content) => { + const label = document.createElement("label"); + label.textContent = `Choose up to ${request.maxFiles} files. The Host keeps a private copy until the transfer is released.`; + const input = document.createElement("input"); + input.type = "file"; + input.multiple = request.maxFiles > 1; + label.append(input); + content.append(label); + return () => { + const selected = Array.from(input.files ?? []); + if (selected.length > request.maxFiles) + throw new Error("Too many Chat attachments"); + for (const file of selected) + checkedSize(file.size); + return selected; + }; + }); + if (!files?.length) + return []; + available(); + const picked = files.map((file) => ({ + sourceId: crypto.randomUUID(), + metadata: { + // Initial safe metadata is refined only from the committed immutable Blob. + mimeType: "application/octet-stream", + sizeBytes: file.size, + kind: { tag: "File" } + } + })); + if (sourceStore) { + await sourceStore.putSources(files.map((file, index) => ({ + sourceId: picked[index].sourceId, + blob: file.slice(0, file.size, "application/octet-stream") + }))); + } else { + const db = await openDatabase(); + available(); + await new Promise((resolve, reject) => { + const transaction = db.transaction(SOURCE_STORE, "readwrite", { + durability: "strict" + }); + transaction.oncomplete = () => resolve(); + transaction.onerror = transaction.onabort = () => reject(new Error("Chat file snapshot failed")); + const sources = transaction.objectStore(SOURCE_STORE); + try { + files.forEach((file, index) => { + sources.add({ + blob: file.slice(0, file.size, "application/octet-stream") + }, picked[index].sourceId); + }); + } catch { + transaction.abort(); + } + }); + } + try { + for (const file of picked) { + if (disposed) + break; + const record = sourceStore ? { blob: await sourceStore.readSource(file.sourceId) } : await store("readonly", (sources) => sources.get(file.sourceId)); + if (!record || !(record.blob instanceof Blob)) + throw new Error("Chat file snapshot is unavailable"); + file.metadata = await inspectNativeChatFileMetadata(record.blob, mediaAbort.signal); + } + if (!disposed) + return picked; + } catch { + await Promise.all(picked.map((file) => host.releaseChatFile(file.sourceId))); + if (!disposed) + throw new Error("Chat file snapshot inspection failed"); + return []; + } + await Promise.all(picked.map((file) => host.releaseChatFile(file.sourceId))); + return []; + }, + async readChatFile(sourceId, offset, length) { + checkedSize(length); + if (length > MAX_READ_SIZE || offset < 0n || offset > BigInt(MAX_FILE_SIZE)) { + throw new Error("Chat file read is out of bounds"); + } + const record = sourceStore ? { blob: await sourceStore.readSource(sourceId) } : await store("readonly", (sources) => sources.get(sourceId)); + if (!record || !(record.blob instanceof Blob)) + throw new Error("Chat file source is unavailable"); + checkedSize(record.blob.size); + if (offset + BigInt(length) > BigInt(record.blob.size)) + throw new Error("Chat file read is out of bounds"); + const start = Number(offset); + const bytes2 = new Uint8Array(await record.blob.slice(start, start + length).arrayBuffer()); + if (bytes2.byteLength !== length) + throw new Error("Chat file snapshot read failed"); + return bytes2; + }, + async releaseChatFile(sourceId) { + if (sourceStore) { + await sourceStore.releaseSource(sourceId); + return; + } + await store("readwrite", (sources) => sources.delete(sourceId), true); + }, + async beginChatFileExport(request) { + available(); + checkedSize(request.metadata.sizeBytes); + const id = crypto.randomUUID(); + const filename = nativeChatExportFilename(request.metadata); + const entry = await prompt("Save Chat attachment", request, "Choose destination", (content) => { + const description = document.createElement("p"); + description.textContent = `${request.metadata.sizeBytes} bytes. Saved as a download, never opened or executed automatically.`; + content.append(description); + return async () => { + const picker = window.showSaveFilePicker; + let writer; + let removePartial = async () => { + }; + let presentCompleted; + if (picker) { + const handle = await picker.call(window, { + suggestedName: filename + }); + writer = await handle.createWritable(); + } else { + if (!navigator.storage?.getDirectory) + throw new Error("Streaming Chat file export is unavailable"); + const root = await navigator.storage.getDirectory(); + const directory = await root.getDirectoryHandle("truapi-chat-exports", { create: true }); + const handle = await directory.getFileHandle(id, { + create: true + }); + removePartial = () => directory.removeEntry(id); + try { + writer = await handle.createWritable(); + } catch (error) { + await removePartial(); + throw error; + } + presentCompleted = async () => { + const file = await handle.getFile(); + const url = URL.createObjectURL(file.slice(0, file.size, "application/octet-stream")); + let downloaded = false; + try { + await prompt("Chat attachment ready", request, "Done", (body) => { + const link = document.createElement("a"); + link.textContent = "Download attachment"; + link.href = url; + link.download = filename; + link.onclick = () => { + downloaded = true; + }; + body.append(link); + return () => void 0; + }); + } finally { + URL.revokeObjectURL(url); + if (downloaded) + await removePartial(); + } + }; + } + const result = { + writer, + size: request.metadata.sizeBytes, + written: 0, + queue: Promise.resolve(), + removePartial, + presentCompleted + }; + if (disposed) { + try { + await writer.abort(); + } finally { + await removePartial(); + } + return void 0; + } + return result; + }; + }); + if (!entry) + return void 0; + if (disposed) { + await abortExport(id, entry); + return void 0; + } + exports2.set(id, entry); + return id; + }, + async writeChatFileExport(exportId, offset, data) { + available(); + await withExport(exportId, async (entry) => { + if (data.byteLength > MAX_READ_SIZE || offset !== BigInt(entry.written) || BigInt(data.byteLength) + offset > BigInt(entry.size)) { + throw new Error("Chat file export write is out of bounds or not contiguous"); + } + try { + await entry.writer.write(data); + entry.written += data.byteLength; + } catch { + await abortExport(exportId, entry); + throw new Error("Chat file export write failed"); + } + }); + }, + async finishChatFileExport(exportId) { + available(); + await withExport(exportId, async (entry) => { + if (entry.written !== entry.size) + throw new Error("Chat file export is incomplete"); + try { + await entry.writer.close(); + } catch { + await abortExport(exportId, entry); + throw new Error("Chat file export could not be saved"); + } + exports2.delete(exportId); + if (entry.presentCompleted && !disposed) + await entry.presentCompleted(); + }); + }, + async cancelChatFileExport(exportId) { + const entry = exports2.get(exportId); + if (!entry) + return; + const operation = entry.queue.then(async () => { + if (exports2.get(exportId) === entry) + await abortExport(exportId, entry); + }); + entry.queue = operation.catch(() => { + }); + await operation; + }, + dispose() { + if (disposed) + return; + disposed = true; + mediaAbort.abort(); + for (const abort of dialogs) + abort(); + for (const id of exports2.keys()) + void host.cancelChatFileExport(id).catch(() => { + }); + const opening = database; + database = void 0; + void opening?.then((db) => db.close(), () => { + }); + } + }; + return host; +} + // dist/wallet-allowances.js function validateAllowanceProductIds(value) { if (!Array.isArray(value) || value.length > 32 || new Set(value).size !== value.length) { @@ -916,6 +1798,7 @@ var nextProductSubtreePublicKeyRequestId = 0; var nextSessionActivationRequestId = 0; var nextLocalIdentityRequestId = 0; var nextAllowanceSnapshotRequestId = 0; +var nextNativeChatContactsRequestId = 0; var nextActionRequestId = 0; var nextRenderId = 0; function encodePermissionAuthorizationRequest(request) { @@ -996,6 +1879,26 @@ function persistLogLevel(level) { } var devLogLevelOverride = readPersistedLogLevel(); var devGlobalTargets = /* @__PURE__ */ new Set(); +var NATIVE_CHAT_FILE_CALLBACKS = { + pickChatFiles: true, + readChatFile: true, + releaseChatFile: true, + beginChatFileExport: true, + writeChatFileExport: true, + finishChatFileExport: true, + cancelChatFileExport: true +}; +async function discardChatFileCallback(state, name, value) { + try { + if (name === "pickChatFiles" && value instanceof Uint8Array) { + await Promise.all((0, import_scale3.Vector)(NativeChatPickedFile).dec(value).map((file) => state.rawCallbacks.releaseChatFile(file.sourceId))); + } else if (name === "beginChatFileExport" && typeof value === "string") { + state.chatFileExports.delete(value); + await state.rawCallbacks.cancelChatFileExport(value); + } + } catch { + } +} function operationIdFrom(value) { if (!(value instanceof Uint8Array)) return null; @@ -1017,7 +1920,8 @@ function operationHold(encodedProduct, id) { function handleCallbackRequest(state, msg) { if (state.disposed) return; - const callbacks = msg.coreId === void 0 ? state.rawCallbacks : state.coreCallbacks.get(msg.coreId); + const hostWalletCallback = COINAGE_WALLET_CALLBACKS[msg.name] === true; + const callbacks = msg.coreId === void 0 || hostWalletCallback ? state.rawCallbacks : state.coreCallbacks.get(msg.coreId); const fn = callbacks && Object.hasOwn(callbacks, msg.name) ? callbacks[msg.name] : void 0; if (!fn) { state.worker.postMessage({ @@ -1031,10 +1935,14 @@ function handleCallbackRequest(state, msg) { Promise.resolve().then(() => { if (state.disposed) throw new Error("Host runtime is unavailable"); - if (msg.coreId !== void 0 && !state.coreCallbacks.has(msg.coreId)) + if (!hostWalletCallback && msg.coreId !== void 0 && !state.coreCallbacks.has(msg.coreId)) throw new Error("Product callbacks are unavailable"); return fn(...msg.args); - }).then((value) => { + }).then(async (value) => { + if (state.disposed) { + await discardChatFileCallback(state, msg.name, value); + return; + } if (msg.name === "beginOperation") { const id = operationIdFrom(value); const hold = id === null ? null : operationHold(msg.args[0], id); @@ -1051,19 +1959,46 @@ function handleCallbackRequest(state, msg) { teardown(state, new Error("runtime disposed"), false); } } - state.worker.postMessage({ - kind: "callbackResponse", - requestId: msg.requestId, - ok: true, - value - }); + if (msg.name === "beginChatFileExport" && typeof value === "string") { + state.chatFileExports.add(value); + } else if (msg.name === "finishChatFileExport" || msg.name === "cancelChatFileExport") { + state.chatFileExports.delete(msg.args[0]); + } + try { + state.worker.postMessage({ + kind: "callbackResponse", + requestId: msg.requestId, + ok: true, + value + }); + } catch { + await discardChatFileCallback(state, msg.name, value); + if (state.disposed) + return; + try { + state.worker.postMessage({ + kind: "callbackResponse", + requestId: msg.requestId, + ok: false, + error: "Host callback result could not be serialized" + }); + } catch { + teardown(state, new Error("Host callback transport is unavailable"), true); + } + } }, (err2) => { - state.worker.postMessage({ - kind: "callbackResponse", - requestId: msg.requestId, - ok: false, - error: errorMessage(err2) - }); + if (state.disposed) + return; + try { + state.worker.postMessage({ + kind: "callbackResponse", + requestId: msg.requestId, + ok: false, + error: hostWalletCallback ? "Native Coinage wallet operation failed" : NATIVE_CHAT_FILE_CALLBACKS[msg.name] ? "Native Chat file operation failed" : errorMessage(err2) + }); + } catch { + teardown(state, new Error("Host callback transport is unavailable"), true); + } }); } function handleSubscriptionStart(state, msg) { @@ -1111,9 +2046,21 @@ function handleSubscriptionStop(state, msg) { } } async function handleChainConnectStart(state, msg) { - const chainConnect = state.rawCallbacks.chainConnect; + if (state.disposed) + return; + if (state.chainConnections.has(msg.connId) || state.chainConnections.size >= MAX_JSON_RPC_CONNECTIONS) { + state.worker.postMessage({ + kind: "chainConnectAck", + connId: msg.connId, + ok: false, + error: "JSON-RPC connection limit reached or duplicate connection id" + }); + return; + } + const entry = { connection: null, closed: false }; + state.chainConnections.set(msg.connId, entry); const onResponse = (json) => { - if (state.disposed) + if (state.disposed || entry.closed) return; state.worker.postMessage({ kind: "chainResponse", @@ -1121,54 +2068,84 @@ async function handleChainConnectStart(state, msg) { json }); }; + const onClosed = () => { + if (state.disposed || entry.closed) + return; + handleChainClose(state, msg); + state.worker.postMessage({ + kind: "chainClosed", + connId: msg.connId + }); + }; try { - const conn = await chainConnect(msg.genesisHash, onResponse); - if (!conn) { - state.worker.postMessage({ - kind: "chainConnectAck", - connId: msg.connId, - ok: false, - error: `chainConnect returned null for genesisHash ${msg.genesisHash}` - }); + const conn = await (msg.kind === "hopConnectStart" ? state.rawCallbacks.hopConnect(msg.genesisHash, msg.endpoint, onResponse, onClosed) : state.rawCallbacks.chainConnect(msg.genesisHash, onResponse, onClosed)); + if (state.disposed || entry.closed) { + state.chainConnections.delete(msg.connId); + conn?.close(); return; } - state.chainConnections.set(msg.connId, conn); + if (!conn) + throw new Error(`${msg.kind} returned no connection`); + entry.connection = conn; state.worker.postMessage({ kind: "chainConnectAck", connId: msg.connId, ok: true }); } catch (err2) { - state.worker.postMessage({ - kind: "chainConnectAck", - connId: msg.connId, - ok: false, - error: errorMessage(err2) - }); + state.chainConnections.delete(msg.connId); + const report = !state.disposed && !entry.closed; + entry.closed = true; + try { + entry.connection?.close(); + } catch { + console.warn("[truapi worker] JSON-RPC close failed"); + } finally { + if (report) { + state.worker.postMessage({ + kind: "chainConnectAck", + connId: msg.connId, + ok: false, + error: msg.kind === "hopConnectStart" ? "HOP connection unavailable" : errorMessage(err2) + }); + } + } } } function handleChainSend(state, msg) { - const conn = state.chainConnections.get(msg.connId); - if (!conn) + const entry = state.chainConnections.get(msg.connId); + if (!entry?.connection || entry.closed) return; try { if (debugLoggingEnabled(state)) { - console.debug("[truapi worker] chainSend", msg.connId, msg.request); + console.debug("[truapi worker] chainSend", msg.connId); + } + entry.connection.send(msg.request); + } catch { + console.warn("[truapi worker] JSON-RPC send failed"); + if (!entry.closed) { + handleChainClose(state, msg); + if (!state.disposed) { + state.worker.postMessage({ + kind: "chainClosed", + connId: msg.connId + }); + } } - conn.send(msg.request); - } catch (err2) { - console.warn("[truapi worker] chain send threw:", err2); } } function handleChainClose(state, msg) { - const conn = state.chainConnections.get(msg.connId); - if (!conn) + const entry = state.chainConnections.get(msg.connId); + if (!entry || entry.closed) + return; + entry.closed = true; + if (!entry.connection) return; state.chainConnections.delete(msg.connId); try { - conn.close(); - } catch (err2) { - console.warn("[truapi worker] chain close threw:", err2); + entry.connection.close(); + } catch { + console.warn("[truapi worker] JSON-RPC close failed"); } } function settlePending(map, requestId, result) { @@ -1219,6 +2196,7 @@ function rejectPendingRuntimeRequests(state, error) { rejectAll(state.pendingSessionActivations, error); rejectAll(state.pendingLocalIdentities, error); rejectAll(state.pendingAllowanceSnapshots, error); + rejectAll(state.pendingNativeChatContacts, error); rejectAll(state.pendingPermissionAuthorizationStatuses, error); rejectAll(state.pendingPermissionAuthorizationStatusBatches, error); rejectAll(state.pendingSetPermissionAuthorizationStatuses, error); @@ -1290,6 +2268,7 @@ function invalidateAllowanceIdentity(state) { state.identityGeneration++; state.identityAccountId = null; rejectAll(state.pendingAllowanceSnapshots, new Error("local identity activation changed")); + rejectAll(state.pendingNativeChatContacts, new Error("local identity activation changed")); } async function getWalletAllowanceSnapshot(state, input) { if (state.disposed || state.disposePending) { @@ -1335,6 +2314,39 @@ async function getWalletAllowanceSnapshot(state, input) { } return promise; } +async function getNativeChatContacts(state) { + if (state.disposed || state.disposePending) { + throw state.closedError ?? new Error("runtime disposed"); + } + if (state.role !== "signing" || state.pendingSessionActivations.size > 0 || state.pendingDisconnects.size > 0) { + throw new Error("native Chat contacts require a current local signing session"); + } + const generation = state.identityGeneration; + const requestId = ++nextNativeChatContactsRequestId; + const { promise, resolve, reject } = Promise.withResolvers(); + state.pendingNativeChatContacts.set(requestId, { + resolve(snapshot) { + if (generation !== state.identityGeneration || state.disposePending) { + reject(new Error("local identity activation changed")); + } else { + resolve(snapshot); + } + }, + reject + }); + try { + state.worker.postMessage({ + kind: "getNativeChatContacts", + requestId + }); + } catch (error) { + settlePending(state.pendingNativeChatContacts, requestId, { + ok: false, + error: errorMessage(error) + }); + } + return promise; +} function closeCoreState(core, error) { if (core.disposed) return; @@ -1370,13 +2382,20 @@ function teardown(state, error, fault) { } } state.subscriptionDisposers.clear(); - for (const conn of state.chainConnections.values()) { + for (const entry of state.chainConnections.values()) { + entry.closed = true; try { - conn.close(); + entry.connection?.close(); } catch { } } state.chainConnections.clear(); + for (const id of state.chatFileExports) { + void state.rawCallbacks.cancelChatFileExport(id).catch(() => { + }); + } + state.chatFileExports.clear(); + state.disposeNativeChatFiles(); for (const productId of [...state.wantedWorkers]) { handleWorkerDemandChanged(state, productId, false); } @@ -1399,7 +2418,11 @@ function createWebWorkerSigningHostRuntime(worker, host, options) { }); } function createWebWorkerHostRuntime(worker, host, options) { - const callbacks = createWasmRawCallbacks(host); + const browserFiles = host.nativeChatFiles ? void 0 : createBrowserNativeChatFilesHost(); + const callbacks = createWasmRawCallbacks({ + ...host, + nativeChatFiles: host.nativeChatFiles ?? browserFiles + }); return new Promise((resolve, reject) => { const state = { worker, @@ -1408,6 +2431,7 @@ function createWebWorkerHostRuntime(worker, host, options) { identityAccountId: null, identityGeneration: 0, pendingAllowanceSnapshots: /* @__PURE__ */ new Map(), + pendingNativeChatContacts: /* @__PURE__ */ new Map(), rawCallbacks: callbacks, coreCallbacks: /* @__PURE__ */ new Map(), cores: /* @__PURE__ */ new Map(), @@ -1418,6 +2442,8 @@ function createWebWorkerHostRuntime(worker, host, options) { disposeGraceTimer: void 0, operationGraceMs: options.operationGraceMs ?? 3e4, chainConnections: /* @__PURE__ */ new Map(), + chatFileExports: /* @__PURE__ */ new Set(), + disposeNativeChatFiles: () => browserFiles?.dispose(), pendingDisconnects: /* @__PURE__ */ new Map(), pendingSessionActivations: /* @__PURE__ */ new Map(), pendingLocalIdentities: /* @__PURE__ */ new Map(), @@ -1469,7 +2495,7 @@ function createWebWorkerHostRuntime(worker, host, options) { if (!core || core.disposed) break; if (debugLoggingEnabled(state)) { - console.debug("[truapi worker] frame <-", (0, import_scale2.bytesToHex)(msg.bytes)); + console.debug("[truapi worker] frame <-", (0, import_scale3.bytesToHex)(msg.bytes)); } for (const listener of [...core.listeners]) listener(msg.bytes); @@ -1495,6 +2521,9 @@ function createWebWorkerHostRuntime(worker, host, options) { case "walletAllowanceSnapshotResponse": settlePending(state.pendingAllowanceSnapshots, msg.requestId, msg.ok ? { ok: true, value: msg.snapshot } : { ok: false, error: msg.error }); break; + case "nativeChatContactsResponse": + settlePending(state.pendingNativeChatContacts, msg.requestId, msg.ok ? { ok: true, value: msg.snapshot } : { ok: false, error: msg.error }); + break; case "permissionAuthorizationStatusResponse": handlePermissionAuthorizationStatusResponse(state, msg); break; @@ -1569,8 +2598,9 @@ function createWebWorkerHostRuntime(worker, host, options) { handleSubscriptionStop(state, msg); break; case "chainConnectStart": + case "hopConnectStart": if (debugLoggingEnabled(state)) { - console.debug("[truapi worker] chainConnectStart", msg.connId); + console.debug("[truapi worker]", msg.kind, msg.connId); } void handleChainConnectStart(state, msg); break; @@ -1624,6 +2654,8 @@ function createWebWorkerHostRuntime(worker, host, options) { chat: host.chat !== void 0, permissionStatus: host.permissionStatus !== void 0, pocket: host.pocket !== void 0, + identityBackend: host.identityBackend !== void 0, + coinageWallet: callbacks.nativeCoinage !== void 0, contacts: host.contacts !== void 0 }, debuggerUrl: debuggerDial @@ -1711,6 +2743,8 @@ function buildRuntime(state) { } return new Promise((resolve, reject) => { const coreId = ++state.nextCoreId; + if (callbacks) + state.coreCallbacks.set(coreId, createWasmRawCallbacks(callbacks)); state.pendingCores.set(coreId, { productId: product.productId, resolve, @@ -1728,7 +2762,9 @@ function buildRuntime(state) { chat: callbacks.chat !== void 0, contacts: callbacks.contacts !== void 0, permissionStatus: callbacks.permissionStatus !== void 0, - pocket: callbacks.pocket !== void 0 + pocket: callbacks.pocket !== void 0, + identityBackend: callbacks.identityBackend !== void 0, + coinageWallet: state.rawCallbacks.nativeCoinage !== void 0 } } }); @@ -1778,6 +2814,7 @@ function buildRuntime(state) { }); }, notifyContactsChanged() { + rejectAll(state.pendingNativeChatContacts, new Error("native Chat contacts changed")); postUnlessDisposed(state, { kind: "notifyContactsChanged" }); }, acquireWorker(productId) { @@ -1856,6 +2893,9 @@ function buildRuntime(state) { getWalletAllowanceSnapshot(productIds) { return getWalletAllowanceSnapshot(state, productIds); }, + getNativeChatContacts() { + return getNativeChatContacts(state); + }, registerLocalLiteUsername(baseUsername, identityBackendBaseUrl, onProgress) { return sendLocalIdentityRequest(state, (requestId) => ({ kind: "registerLocalLiteUsername", @@ -1981,7 +3021,7 @@ function buildProvider(state, core, runtime) { if (state.disposed || core.disposed) return; if (debugLoggingEnabled(state)) { - console.debug("[truapi worker] frame ->", (0, import_scale2.bytesToHex)(bytes2)); + console.debug("[truapi worker] frame ->", (0, import_scale3.bytesToHex)(bytes2)); } state.worker.postMessage({ kind: "frame", @@ -2016,7 +3056,7 @@ function buildProvider(state, core, runtime) { if (core.disposed) return void 0; const key = await runtime.getSessionChatIdentityKey(); - return key && (0, import_scale2.bytesToHex)(key); + return key && (0, import_scale3.bytesToHex)(key); }, async getDeviceStatementKey() { if (core.disposed) @@ -2027,13 +3067,13 @@ function buildProvider(state, core, runtime) { if (core.disposed) { throw new Error("product connection is closed"); } - return (0, import_scale2.bytesToHex)(await runtime.getDeviceEncryptionKey()); + return (0, import_scale3.bytesToHex)(await runtime.getDeviceEncryptionKey()); }, async getProductSubtreePublicKey(productId, timeoutMs) { if (core.disposed) return void 0; const key = await runtime.getProductSubtreePublicKey(productId, timeoutMs); - return key && (0, import_scale2.bytesToHex)(key); + return key && (0, import_scale3.bytesToHex)(key); }, getPermissionAuthorizationStatus(request) { if (core.disposed) @@ -2047,8 +3087,9 @@ function buildProvider(state, core, runtime) { return runtime.getPermissionAuthorizationStatuses(core.productId, requests); }, setPermissionAuthorizationStatus(request, status) { - if (core.disposed) - return Promise.resolve(); + if (core.disposed) { + return Promise.reject(core.closedError ?? new Error("product connection is closed")); + } return runtime.setPermissionAuthorizationStatus(core.productId, request, status); }, setLogLevel(level) { @@ -2248,7 +3289,7 @@ function aoutput(out, instance) { throw new RangeError('"digestInto() output" expected to be of length >=' + min); } } -function u32(arr) { +function u322(arr) { return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4)); } function clean(...arrays) { @@ -2647,7 +3688,7 @@ var _BLAKE2 = class { this.blockLen = blockLen; this.outputLen = outputLen; this.buffer = new Uint8Array(blockLen); - this.buffer32 = u32(this.buffer); + this.buffer32 = u322(this.buffer); } update(data) { aexists(this); @@ -2694,7 +3735,7 @@ var _BLAKE2 = class { if (out.byteOffset & 3) throw new RangeError('"digestInto() output" expected 4-byte aligned byteOffset, got ' + out.byteOffset); const state = this.get(); - const out32 = u32(out); + const out32 = u322(out); const full = Math.floor(this.outputLen / 4); for (let i = 0; i < full; i++) out32[i] = swap8IfBE(state[i]); @@ -2760,7 +3801,7 @@ var _BLAKE2b = class extends _BLAKE2 { this.v0l ^= this.outputLen | keyLength << 8 | 1 << 16 | 1 << 24; if (salt !== void 0) { abytes(salt, void 0, "salt"); - const slt = u32(salt); + const slt = u322(salt); this.v4l ^= swap8IfBE(slt[0]); this.v4h ^= swap8IfBE(slt[1]); this.v5l ^= swap8IfBE(slt[2]); @@ -2768,7 +3809,7 @@ var _BLAKE2b = class extends _BLAKE2 { } if (personalization !== void 0) { abytes(personalization, void 0, "personalization"); - const pers = u32(personalization); + const pers = u322(personalization); this.v6l ^= swap8IfBE(pers[0]); this.v6h ^= swap8IfBE(pers[1]); this.v7l ^= swap8IfBE(pers[2]); @@ -2998,7 +4039,7 @@ function parseFilter(raw) { } return { kind: "MatchAll", topics: [] }; } -function matches(subscription, topics) { +function matches2(subscription, topics) { if (subscription.topics.length === 0 || topics === void 0) return true; return subscription.kind === "MatchAll" ? subscription.topics.every((topic) => topics.includes(topic)) : subscription.topics.some((topic) => topics.includes(topic)); @@ -3024,7 +4065,7 @@ function createLoopbackStatements() { const topics = topicsOf(encoded); let delivered = 0; for (const subscription of subscriptions) { - if (!matches(subscription, topics)) + if (!matches2(subscription, topics)) continue; notify(subscription, encoded); delivered += 1; @@ -3060,7 +4101,7 @@ function createLoopbackStatements() { for (const statement of retained) { if (statement.fromProduct) continue; - if (matches(subscription, topicsOf(statement.encoded))) { + if (matches2(subscription, topicsOf(statement.encoded))) { notify(subscription, statement.encoded); } } diff --git a/vendor/truapi-host/dist/wasm-module.d.ts b/vendor/truapi-host/dist/wasm-module.d.ts index 740136263..bcc75afbb 100644 --- a/vendor/truapi-host/dist/wasm-module.d.ts +++ b/vendor/truapi-host/dist/wasm-module.d.ts @@ -1,6 +1,7 @@ import type { PermissionAuthorizationRuntime } from "./worker-permission-authorization.js"; import type { LocalIdentity } from "./worker-protocol.js"; import type { WalletAllowanceSnapshot } from "./wallet-allowances.js"; +import type { NativeChatContactsSnapshot } from "./runtime.js"; /** Cancellable handle on one live render stream inside the core. */ export interface WorkerRendererSubscription { cancel(): void; @@ -56,6 +57,7 @@ export interface WorkerHostRuntime extends PermissionAuthorizationRuntime { } /** The long-lived pairing-host runtime product cores are created from. */ export interface WorkerPairingHostRuntime extends WorkerHostRuntime { + getNativeChatContacts(): Promise; cancelPairing(): void; notifySessionStoreChanged(): void; activateStoredSession(): Promise; @@ -67,8 +69,8 @@ export interface WorkerPairingHostRuntime extends WorkerHostRuntime { * * A signing host owns the user's keys and establishes sessions from local * entropy rather than by pairing with a wallet. It is present only in a core - * built with `wasm-signing-host`; the production `web` bundle is built without - * it, which is why the constructor is optional on {@link WasmModuleShape}. + * built with `wasm-signing-host` (including `web` built with `--signing-host`), + * which is why the constructor is optional on {@link WasmModuleShape}. */ export interface WorkerSigningHostRuntime extends WorkerHostRuntime { activateLocalSession(secret: Uint8Array): Promise; @@ -77,7 +79,7 @@ export interface WorkerSigningHostRuntime extends WorkerHostRuntime { * `account.get_user_id` answers with. */ activateLocalSessionWithIdentity(secret: Uint8Array, liteUsername?: string): Promise; - /** Only on a core built with `wasm-signing-host`. */ + /** Only on a core built with the non-production `test-host` feature. */ setGrantAllowancesUnchecked?(granted: boolean): void; localIdentityContext(): { activationId: string; @@ -87,6 +89,7 @@ export interface WorkerSigningHostRuntime extends WorkerHostRuntime { localLiteRegistrationBody(activationId: string, usernameBase: string, verifier: Uint8Array): Promise; refreshLocalIdentity(activationId: string): Promise; getWalletAllowanceSnapshot(activationId: string, productIds: string[]): Promise; + getNativeChatContacts(): Promise; /** Only on a core built with `wasm-signing-host`. */ setWithheldResources?(tags: string[]): void; } @@ -94,7 +97,7 @@ export interface WorkerSigningHostRuntime extends WorkerHostRuntime { export interface WasmModuleShape { default: (input?: unknown) => Promise; WasmPairingHostRuntime: new (callbacks: unknown, hostConfig: unknown) => WorkerPairingHostRuntime; - /** Only in the `testing` bundle; see {@link WorkerSigningHostRuntime}. */ + /** Only in bundles built with `wasm-signing-host`. */ WasmSigningHostRuntime?: new (callbacks: unknown, hostConfig: unknown) => WorkerSigningHostRuntime; WasmProductRuntime: new (callbacks: unknown, runtimeConfig: unknown) => WorkerProductRuntime; setLogLevel?: (level: string) => void; diff --git a/vendor/truapi-host/dist/wasm/testing/LICENSE-AGPL-3.0 b/vendor/truapi-host/dist/wasm/testing/LICENSE-AGPL-3.0 new file mode 100644 index 000000000..a028880c7 --- /dev/null +++ b/vendor/truapi-host/dist/wasm/testing/LICENSE-AGPL-3.0 @@ -0,0 +1,661 @@ +GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/vendor/truapi-host/dist/wasm/testing/package.json b/vendor/truapi-host/dist/wasm/testing/package.json index 968e2c9d6..3ab8227ab 100644 --- a/vendor/truapi-host/dist/wasm/testing/package.json +++ b/vendor/truapi-host/dist/wasm/testing/package.json @@ -6,11 +6,12 @@ ], "description": "TrUAPI trait and type definitions, and the runtime hosts embed", "version": "0.23.0", - "license": "MIT", + "license": "MIT AND AGPL-3.0-only", "files": [ "truapi_server_bg.wasm", "truapi_server.js", "truapi_server.d.ts", + "LICENSE-AGPL-3.0", "snippets" ], "main": "truapi_server.js", 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 49738a6b1..702732591 100644 --- a/vendor/truapi-host/dist/wasm/testing/truapi_server.d.ts +++ b/vendor/truapi-host/dist/wasm/testing/truapi_server.d.ts @@ -45,6 +45,10 @@ export class WasmPairingHostRuntime { * Disconnect the shared account-authority session. */ disconnectSession(): Promise; + /** + * Pairing hosts cannot expose the signing host's private Chat roster. + */ + getNativeChatContacts(): Promise; /** * Build a shared runtime from host-level platform callbacks and host config. */ @@ -237,6 +241,10 @@ export class WasmSigningHostRuntime { * Disconnect the active wallet-local session. */ disconnectSession(): Promise; + /** + * Read the active signing wallet's trusted native Chat directory for host UI. + */ + getNativeChatContacts(): Promise; /** * Read finalized allowance state for this activation; never allocate or sign. */ @@ -411,6 +419,7 @@ export interface InitOutput { readonly wasmpairinghostruntime_deviceEncryptionKey: (a: number) => number; readonly wasmpairinghostruntime_deviceStatementKey: (a: number, b: number) => void; readonly wasmpairinghostruntime_disconnectSession: (a: number) => number; + readonly wasmpairinghostruntime_getNativeChatContacts: (a: number) => number; readonly wasmpairinghostruntime_new: (a: number, b: number, c: number) => void; readonly wasmpairinghostruntime_notifyContactsChanged: (a: number) => void; readonly wasmpairinghostruntime_notifySessionStoreChanged: (a: number) => void; @@ -440,6 +449,7 @@ export interface InitOutput { readonly wasmsigninghostruntime_clearProductState: (a: number, b: number, c: number) => number; readonly wasmsigninghostruntime_deviceEncryptionKey: (a: number) => number; readonly wasmsigninghostruntime_disconnectSession: (a: number) => number; + readonly wasmsigninghostruntime_getNativeChatContacts: (a: number) => number; readonly wasmsigninghostruntime_getWalletAllowanceSnapshot: (a: number, b: number, c: number, d: number, e: number) => number; readonly wasmsigninghostruntime_localIdentityAuthProof: (a: number, b: number, c: number, d: number, e: number, f: number) => void; readonly wasmsigninghostruntime_localIdentityContext: (a: number, b: number) => void; @@ -457,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_6904: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_6962: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_2970: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_2963: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_6784: (a: number, b: number) => void; - readonly __wasm_bindgen_func_elem_2967: (a: number, b: 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 __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 01233dcf9..bab57384d 100644 --- a/vendor/truapi-host/dist/wasm/testing/truapi_server.js +++ b/vendor/truapi-host/dist/wasm/testing/truapi_server.js @@ -103,6 +103,14 @@ export class WasmPairingHostRuntime { const ret = wasm.wasmpairinghostruntime_disconnectSession(this.__wbg_ptr); return takeObject(ret); } + /** + * Pairing hosts cannot expose the signing host's private Chat roster. + * @returns {Promise} + */ + getNativeChatContacts() { + const ret = wasm.wasmpairinghostruntime_getNativeChatContacts(this.__wbg_ptr); + return takeObject(ret); + } /** * Build a shared runtime from host-level platform callbacks and host config. * @param {any} callbacks @@ -592,6 +600,14 @@ export class WasmSigningHostRuntime { const ret = wasm.wasmsigninghostruntime_disconnectSession(this.__wbg_ptr); return takeObject(ret); } + /** + * Read the active signing wallet's trusted native Chat directory for host UI. + * @returns {Promise} + */ + getNativeChatContacts() { + const ret = wasm.wasmsigninghostruntime_getNativeChatContacts(this.__wbg_ptr); + return takeObject(ret); + } /** * Read finalized allowance state for this activation; never allocate or sign. * @param {string} activation_id @@ -1082,6 +1098,12 @@ function __wbg_get_imports() { const ret = getObject(arg0) === undefined; return ret; }, + __wbg___wbindgen_number_get_394265ed1e1b84ee: function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true); + }, __wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) { const obj = getObject(arg1); const ret = typeof(obj) === 'string' ? obj : undefined; @@ -1238,7 +1260,7 @@ function __wbg_get_imports() { const a = state0.a; state0.a = 0; try { - return __wasm_bindgen_func_elem_6962(a, state0.b, arg0, arg1); + return __wasm_bindgen_func_elem_9588(a, state0.b, arg0, arg1); } finally { state0.a = a; } @@ -1375,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: 338, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_6904); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000002: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 85, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2970); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000003: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 199, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_6784); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000004: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 81, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_2963); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000005: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 83, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_2967); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000006: function(arg0) { @@ -1414,7 +1436,12 @@ function __wbg_get_imports() { const ret = getStringFromWasm0(arg0, arg1); return addHeapObject(ret); }, - __wbindgen_cast_0000000000000009: function(arg0, arg1) { + __wbindgen_cast_0000000000000009: function(arg0) { + // Cast intrinsic for `U64 -> Externref`. + const ret = BigInt.asUintN(64, arg0); + return addHeapObject(ret); + }, + __wbindgen_cast_000000000000000a: function(arg0, arg1) { var v0 = getArrayU8FromWasm0(arg0, arg1).slice(); wasm.__wbindgen_export4(arg0, arg1 * 1, 1); // Cast intrinsic for `Vector(U8) -> Externref`. @@ -1435,22 +1462,22 @@ function __wbg_get_imports() { }; } -function __wasm_bindgen_func_elem_6784(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_6784(arg0, arg1); +function __wasm_bindgen_func_elem_9411(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_9411(arg0, arg1); } -function __wasm_bindgen_func_elem_2967(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_2967(arg0, arg1); +function __wasm_bindgen_func_elem_4409(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_4409(arg0, arg1); } -function __wasm_bindgen_func_elem_2970(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_2970(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_4412(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_4412(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_2963(arg0, arg1) { +function __wasm_bindgen_func_elem_4405(arg0, arg1) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_2963(retptr, arg0, arg1); + wasm.__wasm_bindgen_func_elem_4405(retptr, arg0, arg1); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1461,10 +1488,10 @@ function __wasm_bindgen_func_elem_2963(arg0, arg1) { } } -function __wasm_bindgen_func_elem_6904(arg0, arg1, arg2) { +function __wasm_bindgen_func_elem_9530(arg0, arg1, arg2) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_6904(retptr, arg0, arg1, addHeapObject(arg2)); + wasm.__wasm_bindgen_func_elem_9530(retptr, arg0, arg1, addHeapObject(arg2)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1475,8 +1502,8 @@ function __wasm_bindgen_func_elem_6904(arg0, arg1, arg2) { } } -function __wasm_bindgen_func_elem_6962(arg0, arg1, arg2, arg3) { - wasm.__wasm_bindgen_func_elem_6962(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +function __wasm_bindgen_func_elem_9588(arg0, arg1, arg2, arg3) { + wasm.__wasm_bindgen_func_elem_9588(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 85376b5f2..9d226571c 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 0b15ca42d..101de6001 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 @@ -20,6 +20,7 @@ export const wasmpairinghostruntime_clearProductState: (a: number, b: number, c: export const wasmpairinghostruntime_deviceEncryptionKey: (a: number) => number; export const wasmpairinghostruntime_deviceStatementKey: (a: number, b: number) => void; export const wasmpairinghostruntime_disconnectSession: (a: number) => number; +export const wasmpairinghostruntime_getNativeChatContacts: (a: number) => number; export const wasmpairinghostruntime_new: (a: number, b: number, c: number) => void; export const wasmpairinghostruntime_notifyContactsChanged: (a: number) => void; export const wasmpairinghostruntime_notifySessionStoreChanged: (a: number) => void; @@ -49,6 +50,7 @@ export const wasmsigninghostruntime_activateLocalSessionWithIdentity: (a: number export const wasmsigninghostruntime_clearProductState: (a: number, b: number, c: number) => number; export const wasmsigninghostruntime_deviceEncryptionKey: (a: number) => number; export const wasmsigninghostruntime_disconnectSession: (a: number) => number; +export const wasmsigninghostruntime_getNativeChatContacts: (a: number) => number; export const wasmsigninghostruntime_getWalletAllowanceSnapshot: (a: number, b: number, c: number, d: number, e: number) => number; export const wasmsigninghostruntime_localIdentityAuthProof: (a: number, b: number, c: number, d: number, e: number, f: number) => void; export const wasmsigninghostruntime_localIdentityContext: (a: number, b: number) => void; @@ -66,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_6904: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_6962: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_2970: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_2963: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_6784: (a: number, b: number) => void; -export const __wasm_bindgen_func_elem_2967: (a: number, b: 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 __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/LICENSE-AGPL-3.0 b/vendor/truapi-host/dist/wasm/web/LICENSE-AGPL-3.0 new file mode 100644 index 000000000..a028880c7 --- /dev/null +++ b/vendor/truapi-host/dist/wasm/web/LICENSE-AGPL-3.0 @@ -0,0 +1,661 @@ +GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/vendor/truapi-host/dist/wasm/web/package.json b/vendor/truapi-host/dist/wasm/web/package.json index 968e2c9d6..3ab8227ab 100644 --- a/vendor/truapi-host/dist/wasm/web/package.json +++ b/vendor/truapi-host/dist/wasm/web/package.json @@ -6,11 +6,12 @@ ], "description": "TrUAPI trait and type definitions, and the runtime hosts embed", "version": "0.23.0", - "license": "MIT", + "license": "MIT AND AGPL-3.0-only", "files": [ "truapi_server_bg.wasm", "truapi_server.js", "truapi_server.d.ts", + "LICENSE-AGPL-3.0", "snippets" ], "main": "truapi_server.js", 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 587342858..93261ead2 100644 --- a/vendor/truapi-host/dist/wasm/web/truapi_server.d.ts +++ b/vendor/truapi-host/dist/wasm/web/truapi_server.d.ts @@ -45,6 +45,10 @@ export class WasmPairingHostRuntime { * Disconnect the shared account-authority session. */ disconnectSession(): Promise; + /** + * Pairing hosts cannot expose the signing host's private Chat roster. + */ + getNativeChatContacts(): Promise; /** * Build a shared runtime from host-level platform callbacks and host config. */ @@ -237,6 +241,10 @@ export class WasmSigningHostRuntime { * Disconnect the active wallet-local session. */ disconnectSession(): Promise; + /** + * Read the active signing wallet's trusted native Chat directory for host UI. + */ + getNativeChatContacts(): Promise; /** * Read finalized allowance state for this activation; never allocate or sign. */ @@ -383,6 +391,7 @@ export interface InitOutput { readonly wasmpairinghostruntime_deviceEncryptionKey: (a: number) => number; readonly wasmpairinghostruntime_deviceStatementKey: (a: number, b: number) => void; readonly wasmpairinghostruntime_disconnectSession: (a: number) => number; + readonly wasmpairinghostruntime_getNativeChatContacts: (a: number) => number; readonly wasmpairinghostruntime_new: (a: number, b: number, c: number) => void; readonly wasmpairinghostruntime_notifyContactsChanged: (a: number) => void; readonly wasmpairinghostruntime_notifySessionStoreChanged: (a: number) => void; @@ -412,6 +421,7 @@ export interface InitOutput { readonly wasmsigninghostruntime_clearProductState: (a: number, b: number, c: number) => number; readonly wasmsigninghostruntime_deviceEncryptionKey: (a: number) => number; readonly wasmsigninghostruntime_disconnectSession: (a: number) => number; + readonly wasmsigninghostruntime_getNativeChatContacts: (a: number) => number; readonly wasmsigninghostruntime_getWalletAllowanceSnapshot: (a: number, b: number, c: number, d: number, e: number) => number; readonly wasmsigninghostruntime_localIdentityAuthProof: (a: number, b: number, c: number, d: number, e: number, f: number) => void; readonly wasmsigninghostruntime_localIdentityContext: (a: number, b: number) => void; @@ -427,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_6887: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_6945: (a: number, b: number, c: number, d: number) => void; - readonly __wasm_bindgen_func_elem_2963: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_2956: (a: number, b: number, c: number) => void; - readonly __wasm_bindgen_func_elem_6767: (a: number, b: number) => void; - readonly __wasm_bindgen_func_elem_2960: (a: number, b: 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 __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 59ee909e5..66ea9e24d 100644 --- a/vendor/truapi-host/dist/wasm/web/truapi_server.js +++ b/vendor/truapi-host/dist/wasm/web/truapi_server.js @@ -103,6 +103,14 @@ export class WasmPairingHostRuntime { const ret = wasm.wasmpairinghostruntime_disconnectSession(this.__wbg_ptr); return takeObject(ret); } + /** + * Pairing hosts cannot expose the signing host's private Chat roster. + * @returns {Promise} + */ + getNativeChatContacts() { + const ret = wasm.wasmpairinghostruntime_getNativeChatContacts(this.__wbg_ptr); + return takeObject(ret); + } /** * Build a shared runtime from host-level platform callbacks and host config. * @param {any} callbacks @@ -592,6 +600,14 @@ export class WasmSigningHostRuntime { const ret = wasm.wasmsigninghostruntime_disconnectSession(this.__wbg_ptr); return takeObject(ret); } + /** + * Read the active signing wallet's trusted native Chat directory for host UI. + * @returns {Promise} + */ + getNativeChatContacts() { + const ret = wasm.wasmsigninghostruntime_getNativeChatContacts(this.__wbg_ptr); + return takeObject(ret); + } /** * Read finalized allowance state for this activation; never allocate or sign. * @param {string} activation_id @@ -1040,6 +1056,12 @@ function __wbg_get_imports() { const ret = getObject(arg0) === undefined; return ret; }, + __wbg___wbindgen_number_get_394265ed1e1b84ee: function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true); + }, __wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) { const obj = getObject(arg1); const ret = typeof(obj) === 'string' ? obj : undefined; @@ -1196,7 +1218,7 @@ function __wbg_get_imports() { const a = state0.a; state0.a = 0; try { - return __wasm_bindgen_func_elem_6945(a, state0.b, arg0, arg1); + return __wasm_bindgen_func_elem_9564(a, state0.b, arg0, arg1); } finally { state0.a = a; } @@ -1333,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: 338, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_6887); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000002: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 85, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2963); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000003: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 200, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`. - const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_6767); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000004: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 81, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_2956); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000005: function(arg0, arg1) { - // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 83, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`. - const ret = makeClosure(arg0, arg1, __wasm_bindgen_func_elem_2960); + // 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); return addHeapObject(ret); }, __wbindgen_cast_0000000000000006: function(arg0) { @@ -1372,7 +1394,12 @@ function __wbg_get_imports() { const ret = getStringFromWasm0(arg0, arg1); return addHeapObject(ret); }, - __wbindgen_cast_0000000000000009: function(arg0, arg1) { + __wbindgen_cast_0000000000000009: function(arg0) { + // Cast intrinsic for `U64 -> Externref`. + const ret = BigInt.asUintN(64, arg0); + return addHeapObject(ret); + }, + __wbindgen_cast_000000000000000a: function(arg0, arg1) { var v0 = getArrayU8FromWasm0(arg0, arg1).slice(); wasm.__wbindgen_export4(arg0, arg1 * 1, 1); // Cast intrinsic for `Vector(U8) -> Externref`. @@ -1393,22 +1420,22 @@ function __wbg_get_imports() { }; } -function __wasm_bindgen_func_elem_6767(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_6767(arg0, arg1); +function __wasm_bindgen_func_elem_9387(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_9387(arg0, arg1); } -function __wasm_bindgen_func_elem_2960(arg0, arg1) { - wasm.__wasm_bindgen_func_elem_2960(arg0, arg1); +function __wasm_bindgen_func_elem_4337(arg0, arg1) { + wasm.__wasm_bindgen_func_elem_4337(arg0, arg1); } -function __wasm_bindgen_func_elem_2963(arg0, arg1, arg2) { - wasm.__wasm_bindgen_func_elem_2963(arg0, arg1, addHeapObject(arg2)); +function __wasm_bindgen_func_elem_4340(arg0, arg1, arg2) { + wasm.__wasm_bindgen_func_elem_4340(arg0, arg1, addHeapObject(arg2)); } -function __wasm_bindgen_func_elem_2956(arg0, arg1) { +function __wasm_bindgen_func_elem_4333(arg0, arg1) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_2956(retptr, arg0, arg1); + wasm.__wasm_bindgen_func_elem_4333(retptr, arg0, arg1); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1419,10 +1446,10 @@ function __wasm_bindgen_func_elem_2956(arg0, arg1) { } } -function __wasm_bindgen_func_elem_6887(arg0, arg1, arg2) { +function __wasm_bindgen_func_elem_9506(arg0, arg1, arg2) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.__wasm_bindgen_func_elem_6887(retptr, arg0, arg1, addHeapObject(arg2)); + wasm.__wasm_bindgen_func_elem_9506(retptr, arg0, arg1, addHeapObject(arg2)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); if (r1) { @@ -1433,8 +1460,8 @@ function __wasm_bindgen_func_elem_6887(arg0, arg1, arg2) { } } -function __wasm_bindgen_func_elem_6945(arg0, arg1, arg2, arg3) { - wasm.__wasm_bindgen_func_elem_6945(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +function __wasm_bindgen_func_elem_9564(arg0, arg1, arg2, arg3) { + wasm.__wasm_bindgen_func_elem_9564(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 064f448ec..2ee5cb137 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 6279f8f9a..8e036c588 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 @@ -19,6 +19,7 @@ export const wasmpairinghostruntime_clearProductState: (a: number, b: number, c: export const wasmpairinghostruntime_deviceEncryptionKey: (a: number) => number; export const wasmpairinghostruntime_deviceStatementKey: (a: number, b: number) => void; export const wasmpairinghostruntime_disconnectSession: (a: number) => number; +export const wasmpairinghostruntime_getNativeChatContacts: (a: number) => number; export const wasmpairinghostruntime_new: (a: number, b: number, c: number) => void; export const wasmpairinghostruntime_notifyContactsChanged: (a: number) => void; export const wasmpairinghostruntime_notifySessionStoreChanged: (a: number) => void; @@ -48,6 +49,7 @@ export const wasmsigninghostruntime_activateLocalSessionWithIdentity: (a: number export const wasmsigninghostruntime_clearProductState: (a: number, b: number, c: number) => number; export const wasmsigninghostruntime_deviceEncryptionKey: (a: number) => number; export const wasmsigninghostruntime_disconnectSession: (a: number) => number; +export const wasmsigninghostruntime_getNativeChatContacts: (a: number) => number; export const wasmsigninghostruntime_getWalletAllowanceSnapshot: (a: number, b: number, c: number, d: number, e: number) => number; export const wasmsigninghostruntime_localIdentityAuthProof: (a: number, b: number, c: number, d: number, e: number, f: number) => void; export const wasmsigninghostruntime_localIdentityContext: (a: number, b: number) => void; @@ -63,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_6887: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_6945: (a: number, b: number, c: number, d: number) => void; -export const __wasm_bindgen_func_elem_2963: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_2956: (a: number, b: number, c: number) => void; -export const __wasm_bindgen_func_elem_6767: (a: number, b: number) => void; -export const __wasm_bindgen_func_elem_2960: (a: number, b: 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 __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.d.ts b/vendor/truapi-host/dist/web/create-worker-host-runtime.d.ts index 3ac8978bd..5bff4ffaa 100644 --- a/vendor/truapi-host/dist/web/create-worker-host-runtime.d.ts +++ b/vendor/truapi-host/dist/web/create-worker-host-runtime.d.ts @@ -1,10 +1,12 @@ -import type { ProductRuntimeConfig, LogLevel, PermissionAuthorizationRequest, PermissionAuthorizationStatus, ProductExecutionKind, RequiredHostCallbacks, TrUApiProductProvider, WorkerDemandChange } from "../index.js"; +import type { ProductRuntimeConfig, LogLevel, NativeChatContactsSnapshot, PermissionAuthorizationRequest, PermissionAuthorizationStatus, ProductExecutionKind, RequiredHostCallbacks, TrUApiProductProvider, WorkerDemandChange } from "../index.js"; import type { HostRole, LocalIdentity, LocalIdentityProgress } from "../worker-protocol.js"; import { type WalletAllowanceSnapshot } from "../wallet-allowances.js"; export type WebWorkerHostConfig = Omit; export type WebWorkerSigningHostConfig = WebWorkerHostConfig & { /** Bare dotNS network suffix (`dot`, `paseo`, or `testnet`). */ networkSuffix: string; + /** Trusted u32 asset instance, required for instance-scoped Coinage runtimes. */ + coinageInstanceId?: number; }; export interface WorkerPairingHostRuntime { /** @@ -29,6 +31,8 @@ export interface WorkerPairingHostRuntime { * removed or blocked, so a contact handle the core cached stops resolving. */ notifyContactsChanged(): void; + /** Host-only native roster. Pairing hosts reject as unsupported. */ + getNativeChatContacts(): Promise; /** * Restore the session persisted in the core's `AuthSession` slot. Resolves * once product frames may use it, so a host can await this at boot before 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 208df20f2..0b1a2534f 100644 --- a/vendor/truapi-host/dist/web/create-worker-host-runtime.js +++ b/vendor/truapi-host/dist/web/create-worker-host-runtime.js @@ -1,10 +1,12 @@ import { HostChatActionSubscribeItem as HostChatActionSubscribeItemCodec, HostRendererActionSubscribeItem as HostRendererActionSubscribeItemCodec, HostWorkerBeginOperationResponse as HostWorkerBeginOperationResponseCodec, ProductRendererRenderRequest as ProductRendererRenderRequestCodec, RendererNode as RendererNodeCodec, } from "@parity/truapi"; -import { PermissionAuthorizationRequest as PermissionAuthorizationRequestCodec, ProductContext as ProductContextCodec, } from "../generated/host-callbacks.js"; +import { NativeChatPickedFile, PermissionAuthorizationRequest as PermissionAuthorizationRequestCodec, ProductContext as ProductContextCodec, } from "../generated/host-callbacks.js"; import { createWasmRawCallbacks } from "../generated/host-callbacks-adapter.js"; import { isLoopbackWsUrl } from "../worker-protocol.js"; -import { bytesToHex } from "@parity/truapi/scale"; +import { COINAGE_WALLET_CALLBACKS, MAX_JSON_RPC_CONNECTIONS, } from "../worker-protocol.js"; +import { bytesToHex, Vector } from "@parity/truapi/scale"; import { startRawSubscription } from "../generated/worker-callbacks.js"; import { errorMessage, toError } from "../error.js"; +import { createBrowserNativeChatFilesHost } from "./native-chat-files.js"; import { validateAllowanceProductIds, } from "../wallet-allowances.js"; function debugLoggingEnabled(state) { return state.logLevel === "debug" || state.logLevel === "trace"; @@ -18,6 +20,7 @@ let nextProductSubtreePublicKeyRequestId = 0; let nextSessionActivationRequestId = 0; let nextLocalIdentityRequestId = 0; let nextAllowanceSnapshotRequestId = 0; +let nextNativeChatContactsRequestId = 0; let nextActionRequestId = 0; let nextRenderId = 0; function encodePermissionAuthorizationRequest(request) { @@ -171,12 +174,32 @@ function persistLogLevel(level) { } let devLogLevelOverride = readPersistedLogLevel(); const devGlobalTargets = new Set(); -/** - * Key one pending-operation hold. `OperationId` is unique per product, not per - * worker, so the product a `beginOperation`/`endOperation` arrived for has to be - * part of the key. Returns null if the encoded product will not decode, which - * drops the hold rather than letting it pin the worker forever. - */ +const NATIVE_CHAT_FILE_CALLBACKS = { + pickChatFiles: true, + readChatFile: true, + releaseChatFile: true, + beginChatFileExport: true, + writeChatFileExport: true, + finishChatFileExport: true, + cancelChatFileExport: true, +}; +/** Reclaim only undelivered selections; delivered sources belong to durable Host state. */ +async function discardChatFileCallback(state, name, value) { + try { + if (name === "pickChatFiles" && value instanceof Uint8Array) { + await Promise.all(Vector(NativeChatPickedFile) + .dec(value) + .map((file) => state.rawCallbacks.releaseChatFile(file.sourceId))); + } + else if (name === "beginChatFileExport" && typeof value === "string") { + state.chatFileExports.delete(value); + await state.rawCallbacks.cancelChatFileExport(value); + } + } + catch { + // A closed/failed backing store is unavailable; never log private handles or payloads. + } +} /** * Read the host-assigned id out of a `beginOperation` response. Returns null if * the response will not decode, so a hold that cannot be keyed is dropped @@ -211,7 +234,8 @@ function operationHold(encodedProduct, id) { function handleCallbackRequest(state, msg) { if (state.disposed) return; - const callbacks = msg.coreId === undefined + const hostWalletCallback = COINAGE_WALLET_CALLBACKS[msg.name] === true; + const callbacks = msg.coreId === undefined || hostWalletCallback ? state.rawCallbacks : state.coreCallbacks.get(msg.coreId); const fn = callbacks && Object.hasOwn(callbacks, msg.name) @@ -230,11 +254,17 @@ function handleCallbackRequest(state, msg) { .then(() => { if (state.disposed) throw new Error("Host runtime is unavailable"); - if (msg.coreId !== undefined && !state.coreCallbacks.has(msg.coreId)) + if (!hostWalletCallback && + msg.coreId !== undefined && + !state.coreCallbacks.has(msg.coreId)) throw new Error("Product callbacks are unavailable"); return fn(...msg.args); }) - .then((value) => { + .then(async (value) => { + if (state.disposed) { + await discardChatFileCallback(state, msg.name, value); + return; + } // Tracked in the success arm only: a rejected begin must not leave a // hold that nothing will ever release. if (msg.name === "beginOperation") { @@ -254,19 +284,55 @@ function handleCallbackRequest(state, msg) { teardown(state, new Error("runtime disposed"), false); } } - state.worker.postMessage({ - kind: "callbackResponse", - requestId: msg.requestId, - ok: true, - value, - }); + if (msg.name === "beginChatFileExport" && typeof value === "string") { + state.chatFileExports.add(value); + } + else if (msg.name === "finishChatFileExport" || + msg.name === "cancelChatFileExport") { + state.chatFileExports.delete(msg.args[0]); + } + try { + state.worker.postMessage({ + kind: "callbackResponse", + requestId: msg.requestId, + ok: true, + value, + }); + } + catch { + await discardChatFileCallback(state, msg.name, value); + if (state.disposed) + return; + try { + state.worker.postMessage({ + kind: "callbackResponse", + requestId: msg.requestId, + ok: false, + error: "Host callback result could not be serialized", + }); + } + catch { + teardown(state, new Error("Host callback transport is unavailable"), true); + } + } }, (err) => { - state.worker.postMessage({ - kind: "callbackResponse", - requestId: msg.requestId, - ok: false, - error: errorMessage(err), - }); + if (state.disposed) + return; + try { + state.worker.postMessage({ + kind: "callbackResponse", + requestId: msg.requestId, + ok: false, + error: hostWalletCallback + ? "Native Coinage wallet operation failed" + : NATIVE_CHAT_FILE_CALLBACKS[msg.name] + ? "Native Chat file operation failed" + : errorMessage(err), + }); + } + catch { + teardown(state, new Error("Host callback transport is unavailable"), true); + } }); } function handleSubscriptionStart(state, msg) { @@ -318,9 +384,22 @@ function handleSubscriptionStop(state, msg) { } } async function handleChainConnectStart(state, msg) { - const chainConnect = state.rawCallbacks.chainConnect; + if (state.disposed) + return; + if (state.chainConnections.has(msg.connId) || + state.chainConnections.size >= MAX_JSON_RPC_CONNECTIONS) { + state.worker.postMessage({ + kind: "chainConnectAck", + connId: msg.connId, + ok: false, + error: "JSON-RPC connection limit reached or duplicate connection id", + }); + return; + } + const entry = { connection: null, closed: false }; + state.chainConnections.set(msg.connId, entry); const onResponse = (json) => { - if (state.disposed) + if (state.disposed || entry.closed) return; state.worker.postMessage({ kind: "chainResponse", @@ -328,18 +407,27 @@ async function handleChainConnectStart(state, msg) { json, }); }; + const onClosed = () => { + if (state.disposed || entry.closed) + return; + handleChainClose(state, msg); + state.worker.postMessage({ + kind: "chainClosed", + connId: msg.connId, + }); + }; try { - const conn = await chainConnect(msg.genesisHash, onResponse); - if (!conn) { - state.worker.postMessage({ - kind: "chainConnectAck", - connId: msg.connId, - ok: false, - error: `chainConnect returned null for genesisHash ${msg.genesisHash}`, - }); + const conn = await (msg.kind === "hopConnectStart" + ? state.rawCallbacks.hopConnect(msg.genesisHash, msg.endpoint, onResponse, onClosed) + : state.rawCallbacks.chainConnect(msg.genesisHash, onResponse, onClosed)); + if (state.disposed || entry.closed) { + state.chainConnections.delete(msg.connId); + conn?.close(); return; } - state.chainConnections.set(msg.connId, conn); + if (!conn) + throw new Error(`${msg.kind} returned no connection`); + entry.connection = conn; state.worker.postMessage({ kind: "chainConnectAck", connId: msg.connId, @@ -347,38 +435,66 @@ async function handleChainConnectStart(state, msg) { }); } catch (err) { - state.worker.postMessage({ - kind: "chainConnectAck", - connId: msg.connId, - ok: false, - error: errorMessage(err), - }); + state.chainConnections.delete(msg.connId); + const report = !state.disposed && !entry.closed; + entry.closed = true; + try { + entry.connection?.close(); + } + catch { + console.warn("[truapi worker] JSON-RPC close failed"); + } + finally { + if (report) { + state.worker.postMessage({ + kind: "chainConnectAck", + connId: msg.connId, + ok: false, + error: msg.kind === "hopConnectStart" + ? "HOP connection unavailable" + : errorMessage(err), + }); + } + } } } function handleChainSend(state, msg) { - const conn = state.chainConnections.get(msg.connId); - if (!conn) + const entry = state.chainConnections.get(msg.connId); + if (!entry?.connection || entry.closed) return; try { if (debugLoggingEnabled(state)) { - console.debug("[truapi worker] chainSend", msg.connId, msg.request); + console.debug("[truapi worker] chainSend", msg.connId); } - conn.send(msg.request); + entry.connection.send(msg.request); } - catch (err) { - console.warn("[truapi worker] chain send threw:", err); + catch { + console.warn("[truapi worker] JSON-RPC send failed"); + if (!entry.closed) { + handleChainClose(state, msg); + if (!state.disposed) { + state.worker.postMessage({ + kind: "chainClosed", + connId: msg.connId, + }); + } + } } } function handleChainClose(state, msg) { - const conn = state.chainConnections.get(msg.connId); - if (!conn) + const entry = state.chainConnections.get(msg.connId); + if (!entry || entry.closed) + return; + entry.closed = true; + // Keep a closed opening entry counted until its late handle can be closed. + if (!entry.connection) return; state.chainConnections.delete(msg.connId); try { - conn.close(); + entry.connection.close(); } - catch (err) { - console.warn("[truapi worker] chain close threw:", err); + catch { + console.warn("[truapi worker] JSON-RPC close failed"); } } function settlePending(map, requestId, result) { @@ -431,6 +547,7 @@ function rejectPendingRuntimeRequests(state, error) { rejectAll(state.pendingSessionActivations, error); rejectAll(state.pendingLocalIdentities, error); rejectAll(state.pendingAllowanceSnapshots, error); + rejectAll(state.pendingNativeChatContacts, error); rejectAll(state.pendingPermissionAuthorizationStatuses, error); rejectAll(state.pendingPermissionAuthorizationStatusBatches, error); rejectAll(state.pendingSetPermissionAuthorizationStatuses, error); @@ -510,6 +627,7 @@ function invalidateAllowanceIdentity(state) { state.identityGeneration++; state.identityAccountId = null; rejectAll(state.pendingAllowanceSnapshots, new Error("local identity activation changed")); + rejectAll(state.pendingNativeChatContacts, new Error("local identity activation changed")); } async function getWalletAllowanceSnapshot(state, input) { if (state.disposed || state.disposePending) { @@ -561,6 +679,43 @@ async function getWalletAllowanceSnapshot(state, input) { } return promise; } +async function getNativeChatContacts(state) { + if (state.disposed || state.disposePending) { + throw state.closedError ?? new Error("runtime disposed"); + } + if (state.role !== "signing" || + state.pendingSessionActivations.size > 0 || + state.pendingDisconnects.size > 0) { + throw new Error("native Chat contacts require a current local signing session"); + } + const generation = state.identityGeneration; + const requestId = ++nextNativeChatContactsRequestId; + const { promise, resolve, reject } = Promise.withResolvers(); + state.pendingNativeChatContacts.set(requestId, { + resolve(snapshot) { + if (generation !== state.identityGeneration || state.disposePending) { + reject(new Error("local identity activation changed")); + } + else { + resolve(snapshot); + } + }, + reject, + }); + try { + state.worker.postMessage({ + kind: "getNativeChatContacts", + requestId, + }); + } + catch (error) { + settlePending(state.pendingNativeChatContacts, requestId, { + ok: false, + error: errorMessage(error), + }); + } + return promise; +} function closeCoreState(core, error) { if (core.disposed) return; @@ -599,15 +754,21 @@ function teardown(state, error, fault) { } } state.subscriptionDisposers.clear(); - for (const conn of state.chainConnections.values()) { + for (const entry of state.chainConnections.values()) { + entry.closed = true; try { - conn.close(); + entry.connection?.close(); } catch { // ignore during teardown } } state.chainConnections.clear(); + for (const id of state.chatFileExports) { + void state.rawCallbacks.cancelChatFileExport(id).catch(() => { }); + } + state.chatFileExports.clear(); + state.disposeNativeChatFiles(); // A worker nothing can call any more is not wanted. for (const productId of [...state.wantedWorkers]) { handleWorkerDemandChanged(state, productId, false); @@ -640,7 +801,13 @@ export function createWebWorkerSigningHostRuntime(worker, host, options) { }); } function createWebWorkerHostRuntime(worker, host, options) { - const callbacks = createWasmRawCallbacks(host); + const browserFiles = host.nativeChatFiles + ? undefined + : createBrowserNativeChatFilesHost(); + const callbacks = createWasmRawCallbacks({ + ...host, + nativeChatFiles: host.nativeChatFiles ?? browserFiles, + }); return new Promise((resolve, reject) => { const state = { worker, @@ -651,6 +818,7 @@ function createWebWorkerHostRuntime(worker, host, options) { identityAccountId: null, identityGeneration: 0, pendingAllowanceSnapshots: new Map(), + pendingNativeChatContacts: new Map(), rawCallbacks: callbacks, coreCallbacks: new Map(), cores: new Map(), @@ -661,6 +829,8 @@ function createWebWorkerHostRuntime(worker, host, options) { disposeGraceTimer: undefined, operationGraceMs: options.operationGraceMs ?? 30_000, chainConnections: new Map(), + chatFileExports: new Set(), + disposeNativeChatFiles: () => browserFiles?.dispose(), pendingDisconnects: new Map(), pendingSessionActivations: new Map(), pendingLocalIdentities: new Map(), @@ -746,6 +916,11 @@ function createWebWorkerHostRuntime(worker, host, options) { ? { ok: true, value: msg.snapshot } : { ok: false, error: msg.error }); break; + case "nativeChatContactsResponse": + settlePending(state.pendingNativeChatContacts, msg.requestId, msg.ok + ? { ok: true, value: msg.snapshot } + : { ok: false, error: msg.error }); + break; case "permissionAuthorizationStatusResponse": handlePermissionAuthorizationStatusResponse(state, msg); break; @@ -827,8 +1002,9 @@ function createWebWorkerHostRuntime(worker, host, options) { handleSubscriptionStop(state, msg); break; case "chainConnectStart": + case "hopConnectStart": if (debugLoggingEnabled(state)) { - console.debug("[truapi worker] chainConnectStart", msg.connId); + console.debug("[truapi worker]", msg.kind, msg.connId); } void handleChainConnectStart(state, msg); break; @@ -886,6 +1062,8 @@ function createWebWorkerHostRuntime(worker, host, options) { chat: host.chat !== undefined, permissionStatus: host.permissionStatus !== undefined, pocket: host.pocket !== undefined, + identityBackend: host.identityBackend !== undefined, + coinageWallet: callbacks.nativeCoinage !== undefined, contacts: host.contacts !== undefined, }, debuggerUrl: debuggerDial, @@ -979,6 +1157,8 @@ function buildRuntime(state) { } return new Promise((resolve, reject) => { const coreId = ++state.nextCoreId; + if (callbacks) + state.coreCallbacks.set(coreId, createWasmRawCallbacks(callbacks)); state.pendingCores.set(coreId, { productId: product.productId, resolve, @@ -999,6 +1179,8 @@ function buildRuntime(state) { contacts: callbacks.contacts !== undefined, permissionStatus: callbacks.permissionStatus !== undefined, pocket: callbacks.pocket !== undefined, + identityBackend: callbacks.identityBackend !== undefined, + coinageWallet: state.rawCallbacks.nativeCoinage !== undefined, }, }), }); @@ -1052,6 +1234,7 @@ function buildRuntime(state) { }); }, notifyContactsChanged() { + rejectAll(state.pendingNativeChatContacts, new Error("native Chat contacts changed")); postUnlessDisposed(state, { kind: "notifyContactsChanged" }); }, acquireWorker(productId) { @@ -1131,6 +1314,9 @@ function buildRuntime(state) { getWalletAllowanceSnapshot(productIds) { return getWalletAllowanceSnapshot(state, productIds); }, + getNativeChatContacts() { + return getNativeChatContacts(state); + }, registerLocalLiteUsername(baseUsername, identityBackendBaseUrl, onProgress) { return sendLocalIdentityRequest(state, (requestId) => ({ kind: "registerLocalLiteUsername", @@ -1344,8 +1530,9 @@ function buildProvider(state, core, runtime) { return runtime.getPermissionAuthorizationStatuses(core.productId, requests); }, setPermissionAuthorizationStatus(request, status) { - if (core.disposed) - return Promise.resolve(); + if (core.disposed) { + return Promise.reject(core.closedError ?? new Error("product connection is closed")); + } return runtime.setPermissionAuthorizationStatus(core.productId, request, status); }, setLogLevel(level) { diff --git a/vendor/truapi-host/dist/web/index.d.ts b/vendor/truapi-host/dist/web/index.d.ts index 96311360e..64894635f 100644 --- a/vendor/truapi-host/dist/web/index.d.ts +++ b/vendor/truapi-host/dist/web/index.d.ts @@ -3,4 +3,7 @@ export { createIframeHost } from "./create-iframe-host.js"; export type { CreateWebWorkerPairingHostRuntimeOptions, CreateWebWorkerSigningHostRuntimeOptions, WebWorkerHostConfig, WebWorkerSigningHostConfig, WebWorkerHostCallbacks, WorkerPairingHostRuntime, WorkerSigningHostRuntime, } from "./create-worker-host-runtime.js"; export { createWebWorkerPairingHostRuntime, createWebWorkerSigningHostRuntime, } from "./create-worker-host-runtime.js"; export type { LocalIdentity, LocalIdentityProgress, } from "../worker-protocol.js"; +export type { NativeChatContact, NativeChatContactsSnapshot, } from "../runtime.js"; +export { createBrowserNativeChatFilesHost } from "./native-chat-files.js"; +export type { BrowserNativeChatFilesHost, BrowserNativeChatFileSourceStore, } from "./native-chat-files.js"; export type { AllowanceCollection, AllowanceObservation, AllowanceSection, AllowanceSlot, AllowancePool, AllowanceClaims, StatementAllowanceSnapshot, PgasClaimsSnapshot, PgasBalancesSnapshot, BulletinQuota, WalletAllowanceSnapshot, } from "../wallet-allowances.js"; diff --git a/vendor/truapi-host/dist/web/index.js b/vendor/truapi-host/dist/web/index.js index e4843a2e0..553bc07e2 100644 --- a/vendor/truapi-host/dist/web/index.js +++ b/vendor/truapi-host/dist/web/index.js @@ -1,2 +1,3 @@ export { createIframeHost } from "./create-iframe-host.js"; export { createWebWorkerPairingHostRuntime, createWebWorkerSigningHostRuntime, } from "./create-worker-host-runtime.js"; +export { createBrowserNativeChatFilesHost } from "./native-chat-files.js"; diff --git a/vendor/truapi-host/dist/web/native-chat-files.d.ts b/vendor/truapi-host/dist/web/native-chat-files.d.ts new file mode 100644 index 000000000..779d45598 --- /dev/null +++ b/vendor/truapi-host/dist/web/native-chat-files.d.ts @@ -0,0 +1,16 @@ +import type { NativeChatFilesHost } from "../generated/host-callbacks.js"; +/** Immutable host-private sources; writes resolve only after durable commit. */ +export interface BrowserNativeChatFileSourceStore { + putSources(sources: readonly { + sourceId: string; + blob: Blob; + }[]): Promise; + readSource(sourceId: string): Promise; + releaseSource(sourceId: string): Promise; +} +export interface BrowserNativeChatFilesHost extends NativeChatFilesHost { + /** Close host UI and cancel partial exports, never release durable sources. */ + dispose(): void; +} +/** Trusted main-window custody. No filename, path or source handle crosses into a Guest. */ +export declare function createBrowserNativeChatFilesHost(sourceStore?: BrowserNativeChatFileSourceStore): BrowserNativeChatFilesHost; diff --git a/vendor/truapi-host/dist/web/native-chat-files.js b/vendor/truapi-host/dist/web/native-chat-files.js new file mode 100644 index 000000000..24b050785 --- /dev/null +++ b/vendor/truapi-host/dist/web/native-chat-files.js @@ -0,0 +1,475 @@ +import { bytesToHex } from "@parity/truapi/scale"; +import { inspectNativeChatFileMetadata, nativeChatExportFilename, } from "./native-chat-media.js"; +const MAX_FILE_SIZE = 0xffff_ffff; +const MAX_READ_SIZE = 2_000_000; +const DATABASE_NAME = "truapi-native-chat-files"; +const SOURCE_STORE = "sources"; +function checkedSize(size) { + if (!Number.isInteger(size) || size < 0 || size > MAX_FILE_SIZE) { + throw new Error("Chat file size exceeds the supported range"); + } +} +function safeLabel(value) { + return value + .replace(/[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/gu, " ") + .slice(0, 200); +} +/** Trusted main-window custody. No filename, path or source handle crosses into a Guest. */ +export function createBrowserNativeChatFilesHost(sourceStore) { + let disposed = false; + let database; + const dialogs = new Set(); + const exports = new Map(); + const mediaAbort = new AbortController(); + function available() { + if (disposed) + throw new Error("Native Chat files are unavailable"); + } + function openDatabase(cleanup = false) { + if (!cleanup) + available(); + if (!database) { + database = new Promise((resolve, reject) => { + if (!globalThis.indexedDB) { + reject(new Error("Durable Chat file storage is unavailable")); + return; + } + const request = indexedDB.open(DATABASE_NAME, 1); + let blocked = false; + request.onupgradeneeded = () => request.result.createObjectStore(SOURCE_STORE); + request.onerror = () => reject(new Error("Durable Chat file storage is unavailable")); + request.onblocked = () => { + blocked = true; + reject(new Error("Durable Chat file storage is blocked")); + }; + request.onsuccess = () => { + const db = request.result; + if (blocked || (disposed && !cleanup)) { + db.close(); + reject(new Error("Native Chat files are unavailable")); + return; + } + db.onversionchange = () => { + db.close(); + database = undefined; + }; + resolve(db); + }; + }).catch((error) => { + database = undefined; + throw error; + }); + } + return database; + } + async function store(mode, action, cleanup = false) { + const db = await openDatabase(cleanup); + if (!cleanup) + available(); + return new Promise((resolve, reject) => { + // Resolve only on commit, not request success: returned sources must already be durable. + const transaction = db.transaction(SOURCE_STORE, mode, { + durability: "strict", + }); + const request = action(transaction.objectStore(SOURCE_STORE)); + transaction.oncomplete = () => { + if (disposed) { + db.close(); + database = undefined; + } + resolve(request.result); + }; + transaction.onerror = transaction.onabort = () => reject(new Error("Chat file storage failed")); + }); + } + function prompt(title, context, actionLabel, configure) { + available(); + if (typeof document === "undefined" || + !document.body || + window.top !== window) { + return Promise.reject(new Error("Trusted Chat file presentation is unavailable")); + } + return new Promise((resolve, reject) => { + const dialog = document.createElement("dialog"); + const heading = document.createElement("h2"); + heading.textContent = title; + const summary = document.createElement("p"); + summary.textContent = `Product: ${safeLabel(context.productId)}\nPeer: ${safeLabel(context.peerUsername ?? "Chat contact")}\nIdentity: ${bytesToHex(context.peerIdentity)}`; + summary.style.whiteSpace = "pre-wrap"; + summary.style.overflowWrap = "anywhere"; + const content = document.createElement("div"); + const accept = document.createElement("button"); + accept.type = "button"; + accept.textContent = actionLabel; + const cancel = document.createElement("button"); + cancel.type = "button"; + cancel.textContent = "Cancel"; + dialog.setAttribute("aria-label", title); + dialog.style.maxWidth = "min(36rem, 90vw)"; + dialog.append(heading, summary, content, accept, cancel); + let settled = false; + let busy = false; + const close = () => { + dialogs.delete(abort); + dialog.close(); + dialog.remove(); + }; + const abort = () => { + if (settled) + return; + close(); + // A native save picker cannot be aborted. Let its result reach the caller, + // which rechecks disposal and aborts the newly-created writable handle. + if (busy && disposed) + return; + settled = true; + resolve(undefined); + }; + dialogs.add(abort); + cancel.onclick = abort; + dialog.oncancel = (event) => { + event.preventDefault(); + if (!busy) + abort(); + }; + try { + const run = configure(content); + accept.onclick = () => { + if (busy || settled) + return; + busy = true; + accept.disabled = cancel.disabled = true; + // Invoke synchronously in this real click's user activation (FSA requires it). + let result; + try { + result = run(); + } + catch (error) { + result = Promise.reject(error); + } + Promise.resolve(result).then((value) => { + if (!settled) { + settled = true; + close(); + resolve(value); + } + }, (error) => { + if (settled) + return; + busy = false; + if (error instanceof DOMException && + error.name === "AbortError") { + abort(); + return; + } + settled = true; + close(); + reject(new Error("Chat file selection or export failed")); + }); + }; + document.body.append(dialog); + dialog.showModal(); + } + catch { + settled = true; + close(); + reject(new Error("Trusted Chat file presentation is unavailable")); + } + }); + } + async function abortExport(id, entry) { + exports.delete(id); + try { + await entry.writer.abort(); + } + catch { + /* The writer may already be closed. */ + } + await entry.removePartial(); + } + function withExport(id, action) { + const entry = exports.get(id); + if (!entry) + return Promise.reject(new Error("Chat file export is unavailable")); + const operation = entry.queue.then(async () => { + if (exports.get(id) !== entry) + throw new Error("Chat file export is unavailable"); + await action(entry); + }); + entry.queue = operation.catch(() => { }); + return operation; + } + const host = { + async pickChatFiles(request) { + checkedSize(request.maxFiles); + if (request.maxFiles === 0) + throw new Error("Chat file selection is unavailable"); + // Do not ask for files if durable custody cannot be established. + if (!sourceStore) + await openDatabase(); + const files = await prompt("Send Chat attachments", request, "Attach files", (content) => { + const label = document.createElement("label"); + label.textContent = `Choose up to ${request.maxFiles} files. The Host keeps a private copy until the transfer is released.`; + const input = document.createElement("input"); + input.type = "file"; + input.multiple = request.maxFiles > 1; + label.append(input); + content.append(label); + return () => { + const selected = Array.from(input.files ?? []); + if (selected.length > request.maxFiles) + throw new Error("Too many Chat attachments"); + for (const file of selected) + checkedSize(file.size); + return selected; + }; + }); + if (!files?.length) + return []; + available(); + const picked = files.map((file) => ({ + sourceId: crypto.randomUUID(), + metadata: { + // Initial safe metadata is refined only from the committed immutable Blob. + mimeType: "application/octet-stream", + sizeBytes: file.size, + kind: { tag: "File" }, + }, + })); + if (sourceStore) { + await sourceStore.putSources(files.map((file, index) => ({ + sourceId: picked[index].sourceId, + blob: file.slice(0, file.size, "application/octet-stream"), + }))); + } + else { + const db = await openDatabase(); + available(); + await new Promise((resolve, reject) => { + const transaction = db.transaction(SOURCE_STORE, "readwrite", { + durability: "strict", + }); + transaction.oncomplete = () => resolve(); + transaction.onerror = transaction.onabort = () => reject(new Error("Chat file snapshot failed")); + const sources = transaction.objectStore(SOURCE_STORE); + try { + files.forEach((file, index) => { + // Snapshot source bytes, never source names or paths. + sources.add({ + blob: file.slice(0, file.size, "application/octet-stream"), + }, picked[index].sourceId); + }); + } + catch { + transaction.abort(); + } + }); + } + try { + // Inspect one bounded header/probe at a time, from the durable snapshot + // rather than the original File, which may since have changed on disk. + for (const file of picked) { + if (disposed) + break; + const record = sourceStore + ? { blob: await sourceStore.readSource(file.sourceId) } + : await store("readonly", (sources) => sources.get(file.sourceId)); + if (!record || !(record.blob instanceof Blob)) + throw new Error("Chat file snapshot is unavailable"); + file.metadata = await inspectNativeChatFileMetadata(record.blob, mediaAbort.signal); + } + if (!disposed) + return picked; + } + catch { + await Promise.all(picked.map((file) => host.releaseChatFile(file.sourceId))); + if (!disposed) + throw new Error("Chat file snapshot inspection failed"); + return []; + } + await Promise.all(picked.map((file) => host.releaseChatFile(file.sourceId))); + return []; + }, + async readChatFile(sourceId, offset, length) { + checkedSize(length); + if (length > MAX_READ_SIZE || + offset < 0n || + offset > BigInt(MAX_FILE_SIZE)) { + throw new Error("Chat file read is out of bounds"); + } + const record = sourceStore + ? { blob: await sourceStore.readSource(sourceId) } + : await store("readonly", (sources) => sources.get(sourceId)); + if (!record || !(record.blob instanceof Blob)) + throw new Error("Chat file source is unavailable"); + checkedSize(record.blob.size); + if (offset + BigInt(length) > BigInt(record.blob.size)) + throw new Error("Chat file read is out of bounds"); + const start = Number(offset); + const bytes = new Uint8Array(await record.blob.slice(start, start + length).arrayBuffer()); + if (bytes.byteLength !== length) + throw new Error("Chat file snapshot read failed"); + return bytes; + }, + async releaseChatFile(sourceId) { + // Worker teardown may release a selection that committed after its consumer disappeared. + if (sourceStore) { + await sourceStore.releaseSource(sourceId); + return; + } + await store("readwrite", (sources) => sources.delete(sourceId), true); + }, + async beginChatFileExport(request) { + available(); + checkedSize(request.metadata.sizeBytes); + const id = crypto.randomUUID(); + const filename = nativeChatExportFilename(request.metadata); + const entry = await prompt("Save Chat attachment", request, "Choose destination", (content) => { + const description = document.createElement("p"); + description.textContent = `${request.metadata.sizeBytes} bytes. Saved as a download, never opened or executed automatically.`; + content.append(description); + return async () => { + const picker = window.showSaveFilePicker; + let writer; + let removePartial = async () => { }; + let presentCompleted; + if (picker) { + const handle = await picker.call(window, { + suggestedName: filename, + }); + writer = await handle.createWritable(); + } + else { + if (!navigator.storage?.getDirectory) + throw new Error("Streaming Chat file export is unavailable"); + const root = await navigator.storage.getDirectory(); + const directory = await root.getDirectoryHandle("truapi-chat-exports", { create: true }); + const handle = await directory.getFileHandle(id, { + create: true, + }); + removePartial = () => directory.removeEntry(id); + try { + writer = await handle.createWritable(); + } + catch (error) { + await removePartial(); + throw error; + } + presentCompleted = async () => { + // getFile supplies a disk-backed snapshot; never concatenate chunks in JS memory. + const file = await handle.getFile(); + const url = URL.createObjectURL(file.slice(0, file.size, "application/octet-stream")); + let downloaded = false; + try { + await prompt("Chat attachment ready", request, "Done", (body) => { + const link = document.createElement("a"); + link.textContent = "Download attachment"; + link.href = url; + link.download = filename; + link.onclick = () => { + downloaded = true; + }; + body.append(link); + return () => undefined; + }); + } + finally { + URL.revokeObjectURL(url); + // Keep an undownloaded completed copy; cancellation must not delete it. + if (downloaded) + await removePartial(); + } + }; + } + const result = { + writer, + size: request.metadata.sizeBytes, + written: 0, + queue: Promise.resolve(), + removePartial, + presentCompleted, + }; + if (disposed) { + try { + await writer.abort(); + } + finally { + await removePartial(); + } + return undefined; + } + return result; + }; + }); + if (!entry) + return undefined; + if (disposed) { + await abortExport(id, entry); + return undefined; + } + exports.set(id, entry); + return id; + }, + async writeChatFileExport(exportId, offset, data) { + available(); + await withExport(exportId, async (entry) => { + if (data.byteLength > MAX_READ_SIZE || + offset !== BigInt(entry.written) || + BigInt(data.byteLength) + offset > BigInt(entry.size)) { + throw new Error("Chat file export write is out of bounds or not contiguous"); + } + try { + await entry.writer.write(data); + entry.written += data.byteLength; + } + catch { + await abortExport(exportId, entry); + throw new Error("Chat file export write failed"); + } + }); + }, + async finishChatFileExport(exportId) { + available(); + await withExport(exportId, async (entry) => { + if (entry.written !== entry.size) + throw new Error("Chat file export is incomplete"); + try { + await entry.writer.close(); + } + catch { + await abortExport(exportId, entry); + throw new Error("Chat file export could not be saved"); + } + // Commit precedes presentation: late cancellation cannot delete a completed user export. + exports.delete(exportId); + if (entry.presentCompleted && !disposed) + await entry.presentCompleted(); + }); + }, + async cancelChatFileExport(exportId) { + const entry = exports.get(exportId); + if (!entry) + return; + const operation = entry.queue.then(async () => { + if (exports.get(exportId) === entry) + await abortExport(exportId, entry); + }); + entry.queue = operation.catch(() => { }); + await operation; + }, + dispose() { + if (disposed) + return; + disposed = true; + mediaAbort.abort(); + for (const abort of dialogs) + abort(); + for (const id of exports.keys()) + void host.cancelChatFileExport(id).catch(() => { }); + const opening = database; + database = undefined; + void opening?.then((db) => db.close(), () => { }); + }, + }; + return host; +} diff --git a/vendor/truapi-host/dist/web/native-chat-media.d.ts b/vendor/truapi-host/dist/web/native-chat-media.d.ts new file mode 100644 index 000000000..02eaf5617 --- /dev/null +++ b/vendor/truapi-host/dist/web/native-chat-media.d.ts @@ -0,0 +1,7 @@ +import type { NativeChatPickedFile } from "../generated/host-callbacks.js"; +type AttachmentMetadata = NativeChatPickedFile["metadata"]; +/** Derive metadata from the durable Blob's bytes, not the original name or File.type. */ +export declare function inspectNativeChatFileMetadata(blob: Blob, signal?: AbortSignal): Promise; +/** Fixed safe basename and a kind-consistent media whitelist, never a supplied path. */ +export declare function nativeChatExportFilename(metadata: AttachmentMetadata): string; +export {}; diff --git a/vendor/truapi-host/dist/web/native-chat-media.js b/vendor/truapi-host/dist/web/native-chat-media.js new file mode 100644 index 000000000..31b2841d6 --- /dev/null +++ b/vendor/truapi-host/dist/web/native-chat-media.js @@ -0,0 +1,349 @@ +const HEADER_LIMIT = 65_536; +const VIDEO_TIMEOUT_MS = 5_000; +const U32_MAX = 0xffff_ffff; +const MP4_BRANDS = [ + "isom", + "iso2", + "iso3", + "iso4", + "iso5", + "iso6", + "mp41", + "mp42", + "avc1", + "M4V ", + "M4VH", + "M4VP", +]; +const PNG_DEPTHS = { + 0: [1, 2, 4, 8, 16], + 2: [8, 16], + 3: [1, 2, 4, 8], + 4: [8, 16], + 6: [8, 16], +}; +function matches(bytes, offset, signature) { + if (offset + signature.length > bytes.length) + return false; + for (let i = 0; i < signature.length; i++) { + if (bytes[offset + i] !== signature.charCodeAt(i)) + return false; + } + return true; +} +/** Only inspect bounded headers; never render images, XML, SVG or HTML. */ +function imageHeader(bytes, fileSize) { + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + if (bytes.length >= 33 && + matches(bytes, 0, "\x89PNG\r\n\x1a\n") && + view.getUint32(8) === 13 && + matches(bytes, 12, "IHDR")) { + const width = view.getUint32(16); + const height = view.getUint32(20); + if (width > 0 && + height > 0 && + width <= 0x7fff_ffff && + height <= 0x7fff_ffff && + PNG_DEPTHS[bytes[25]]?.includes(bytes[24]) && + bytes[26] === 0 && + bytes[27] === 0 && + bytes[28] <= 1) { + return { mimeType: "image/png", width, height }; + } + return undefined; + } + if (bytes.length >= 13 && + (matches(bytes, 0, "GIF87a") || matches(bytes, 0, "GIF89a"))) { + const width = view.getUint16(6, true); + const height = view.getUint16(8, true); + if (width && height) + return { mimeType: "image/gif", width, height }; + return undefined; + } + if (bytes.length >= 4 && bytes[0] === 0xff && bytes[1] === 0xd8) { + let offset = 2; + while (offset + 4 <= bytes.length) { + if (bytes[offset++] !== 0xff) + return undefined; + while (offset < bytes.length && bytes[offset] === 0xff) + offset++; + const marker = bytes[offset++]; + // Dimensions must precede compressed scan data; never search arbitrarily inside it. + if (marker === undefined || + marker === 0xda || + marker === 0xd9 || + marker === 0x00) + return undefined; + if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) + continue; + if (offset + 2 > bytes.length) + return undefined; + const length = view.getUint16(offset); + if (length < 2 || offset + length > bytes.length) + return undefined; + if (marker >= 0xc0 && + marker <= 0xcf && + marker !== 0xc4 && + marker !== 0xc8 && + marker !== 0xcc) { + if (length < 8) + return undefined; + const height = view.getUint16(offset + 3); + const width = view.getUint16(offset + 5); + const components = bytes[offset + 7]; + if (width && + height && + components > 0 && + length === 8 + 3 * components) { + return { mimeType: "image/jpeg", width, height }; + } + return undefined; + } + offset += length; + } + return undefined; + } + if (bytes.length >= 30 && + matches(bytes, 0, "RIFF") && + matches(bytes, 8, "WEBP") && + view.getUint32(4, true) + 8 === fileSize) { + const chunkSize = view.getUint32(16, true); + if (20 + chunkSize + (chunkSize & 1) > fileSize) + return undefined; + if (matches(bytes, 12, "VP8X") && chunkSize === 10) { + const width = 1 + bytes[24] + (bytes[25] << 8) + (bytes[26] << 16); + const height = 1 + bytes[27] + (bytes[28] << 8) + (bytes[29] << 16); + return { mimeType: "image/webp", width, height }; + } + if (matches(bytes, 12, "VP8 ") && + chunkSize >= 10 && + (bytes[20] & 1) === 0 && + matches(bytes, 23, "\x9d\x01\x2a")) { + const width = view.getUint16(26, true) & 0x3fff; + const height = view.getUint16(28, true) & 0x3fff; + if (width && height) + return { mimeType: "image/webp", width, height }; + } + } + if (bytes.length >= 25 && + matches(bytes, 0, "RIFF") && + matches(bytes, 8, "WEBP") && + matches(bytes, 12, "VP8L") && + view.getUint32(4, true) + 8 === fileSize) { + const chunkSize = view.getUint32(16, true); + if (chunkSize >= 5 && + 20 + chunkSize + (chunkSize & 1) <= fileSize && + bytes[20] === 0x2f && + bytes[24] >> 5 === 0) { + const width = 1 + bytes[21] + ((bytes[22] & 0x3f) << 8); + const height = 1 + (bytes[22] >> 6) + (bytes[23] << 2) + ((bytes[24] & 0x0f) << 10); + return { mimeType: "image/webp", width, height }; + } + } + return undefined; +} +/** Decode only the EBML header's bounded integer fields, not its media payload. */ +function ebmlInteger(bytes, offset, id) { + const first = bytes[offset]; + if (first === undefined || first === 0) + return undefined; + let marker = 0x80; + let length = 1; + while ((first & marker) === 0) { + marker >>= 1; + length++; + } + if (length > (id ? 4 : 8) || offset + length > bytes.length) + return undefined; + let value = id ? first : first & (marker - 1); + for (let i = 1; i < length; i++) + value = value * 256 + bytes[offset + i]; + // Unknown-sized elements are not valid inside an EBML header. + if (!Number.isSafeInteger(value) || (!id && value === 2 ** (7 * length) - 1)) + return undefined; + return { value, next: offset + length }; +} +function videoMime(bytes, fileSize) { + if (bytes.length >= 16 && matches(bytes, 4, "ftyp")) { + const size = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0); + if (size < 16 || size > bytes.length || size > fileSize || size % 4 !== 0) + return undefined; + if (matches(bytes, 8, "qt ")) + return "video/quicktime"; + for (const brand of MP4_BRANDS) { + if (matches(bytes, 8, brand)) + return "video/mp4"; + } + return undefined; + } + if (!matches(bytes, 0, "\x1a\x45\xdf\xa3")) + return undefined; + const header = ebmlInteger(bytes, 4, false); + if (!header || header.value > bytes.length - header.next) + return undefined; + const end = header.next + header.value; + if (!matches(bytes, end, "\x18\x53\x80\x67")) + return undefined; + let offset = header.next; + let webm = false; + while (offset < end) { + const id = ebmlInteger(bytes, offset, true); + if (!id || id.next > end) + return undefined; + const size = ebmlInteger(bytes, id.next, false); + if (!size || size.next > end || size.value > end - size.next) + return undefined; + if (id.value === 0x4282) { + if (webm || size.value !== 4 || !matches(bytes, size.next, "webm")) + return undefined; + webm = true; + } + offset = size.next + size.value; + } + return webm ? "video/webm" : undefined; +} +/** Derive metadata from the durable Blob's bytes, not the original name or File.type. */ +export async function inspectNativeChatFileMetadata(blob, signal) { + if (!Number.isInteger(blob.size) || blob.size < 0 || blob.size > U32_MAX) + throw new Error("Chat file size exceeds the supported range"); + const fallback = { + mimeType: "application/octet-stream", + sizeBytes: blob.size, + kind: { tag: "File" }, + }; + if (signal?.aborted) + return fallback; + const bytes = new Uint8Array(await blob.slice(0, HEADER_LIMIT).arrayBuffer()); + if (signal?.aborted) + return fallback; + const image = imageHeader(bytes, blob.size); + if (image) { + return { + mimeType: image.mimeType, + sizeBytes: blob.size, + kind: { + tag: "Image", + value: { + width: image.width, + height: image.height, + thumbnail: undefined, + }, + }, + }; + } + const mimeType = videoMime(bytes, blob.size); + if (!mimeType || typeof document === "undefined") + return fallback; + // Only a whitelisted media container reaches the browser decoder. The element + // is detached, muted, metadata-only and never played or presented to a Guest. + let video; + let url; + try { + video = document.createElement("video"); + video.preload = "metadata"; + video.autoplay = false; + video.muted = true; + video.playsInline = true; + url = URL.createObjectURL(blob.slice(0, blob.size, mimeType)); + } + catch { + return fallback; + } + return new Promise((resolve) => { + let settled = false; + const finish = (metadata) => { + if (settled) + return; + settled = true; + clearTimeout(timer); + signal?.removeEventListener("abort", abort); + video.onloadedmetadata = video.onerror = null; + try { + video.removeAttribute("src"); + video.load(); + } + catch { + // Cleanup failure must not retain the URL or strand the Host selection. + } + finally { + URL.revokeObjectURL(url); + resolve(metadata); + } + }; + const abort = () => finish(fallback); + const timer = setTimeout(abort, VIDEO_TIMEOUT_MS); + signal?.addEventListener("abort", abort, { once: true }); + video.onerror = abort; + video.onloadedmetadata = () => { + const duration = video.duration; + if (!Number.isFinite(duration) || + duration < 0 || + duration > U32_MAX || + video.videoWidth <= 0 || + video.videoHeight <= 0) { + finish(fallback); + } + else { + finish({ + mimeType, + sizeBytes: blob.size, + kind: { + tag: "Video", + value: { + durationSeconds: Math.floor(duration), + thumbnail: undefined, + }, + }, + }); + } + }; + if (signal?.aborted) { + abort(); + return; + } + try { + video.src = url; + video.load(); + } + catch { + abort(); + } + }); +} +const IMAGE_EXTENSIONS = { + "image/png": "png", + "image/jpeg": "jpg", + "image/gif": "gif", + "image/webp": "webp", +}; +const VIDEO_EXTENSIONS = { + "video/mp4": "mp4", + "video/quicktime": "mov", + "video/webm": "webm", +}; +/** Fixed safe basename and a kind-consistent media whitelist, never a supplied path. */ +export function nativeChatExportFilename(metadata) { + let extension = "bin"; + if (metadata.kind.tag === "Image") { + const { width, height } = metadata.kind.value; + if (Number.isInteger(width) && + Number.isInteger(height) && + width > 0 && + height > 0 && + width <= U32_MAX && + height <= U32_MAX && + Object.hasOwn(IMAGE_EXTENSIONS, metadata.mimeType)) { + extension = IMAGE_EXTENSIONS[metadata.mimeType]; + } + } + else if (metadata.kind.tag === "Video") { + const { durationSeconds } = metadata.kind.value; + if (Number.isInteger(durationSeconds) && + durationSeconds >= 0 && + durationSeconds <= U32_MAX && + Object.hasOwn(VIDEO_EXTENSIONS, metadata.mimeType)) { + extension = VIDEO_EXTENSIONS[metadata.mimeType]; + } + } + return `chat-attachment.${extension}`; +} diff --git a/vendor/truapi-host/dist/worker-dispatch.js b/vendor/truapi-host/dist/worker-dispatch.js index b14a101ce..089174cea 100644 --- a/vendor/truapi-host/dist/worker-dispatch.js +++ b/vendor/truapi-host/dist/worker-dispatch.js @@ -38,9 +38,13 @@ export function dispatchChainResponse(connId, json, listeners, postToMain) { try { listener(json); } - catch (err) { + catch { listeners.delete(connId); postToMain({ kind: "chainClose", connId }); - reportDispatchFailure(postToMain, `chain connection ${connId}`, err); + // Response-handler errors may contain private HOP data. + postToMain({ + kind: "disposeError", + error: `JSON-RPC connection ${connId} callback failed`, + }); } } diff --git a/vendor/truapi-host/dist/worker-protocol.d.ts b/vendor/truapi-host/dist/worker-protocol.d.ts index a97747648..32d8cfc48 100644 --- a/vendor/truapi-host/dist/worker-protocol.d.ts +++ b/vendor/truapi-host/dist/worker-protocol.d.ts @@ -1,5 +1,5 @@ import type { OptionalCapabilities } from "./generated/worker-callbacks.js"; -import type { LogLevel, PermissionAuthorizationStatus } from "./runtime.js"; +import type { LogLevel, NativeChatContactsSnapshot, PermissionAuthorizationStatus } from "./runtime.js"; import type { WalletAllowanceSnapshot } from "./wallet-allowances.js"; import type { CallbackName, SubscriptionName } from "./generated/worker-callbacks.js"; /** @@ -7,6 +7,10 @@ import type { CallbackName, SubscriptionName } from "./generated/worker-callback * hand-written protocol aligned with the Rust platform callback catalog. */ export type { CallbackName, SubscriptionName, } from "./generated/worker-callbacks.js"; +/** Shared cap includes connections still opening or closing during an open. */ +export declare const MAX_JSON_RPC_CONNECTIONS = 64; +/** Wallet custody belongs to the runtime, never a product-specific callback bundle. */ +export declare const COINAGE_WALLET_CALLBACKS: Readonly>>; /** * Positional arguments for a callback. The wasm core calls each callback * at a fixed arity; a uniform `unknown[]` keeps the wire protocol simple. @@ -128,6 +132,9 @@ export type MainToWorker = { kind: "getWalletAllowanceSnapshot"; requestId: number; productIds: string[]; +} | { + kind: "getNativeChatContacts"; + requestId: number; } | { kind: "registerLocalLiteUsername"; requestId: number; @@ -215,6 +222,9 @@ export type MainToWorker = { kind: "chainResponse"; connId: number; json: string; +} | { + kind: "chainClosed"; + connId: number; } | { kind: "dispose"; }; @@ -302,6 +312,16 @@ export type WorkerToMain = { requestId: number; ok: false; error: string; +} | { + kind: "nativeChatContactsResponse"; + requestId: number; + ok: true; + snapshot: NativeChatContactsSnapshot; +} | { + kind: "nativeChatContactsResponse"; + requestId: number; + ok: false; + error: string; } | { kind: "permissionAuthorizationStatusResponse"; requestId: number; @@ -432,6 +452,11 @@ export type WorkerToMain = { kind: "chainConnectStart"; connId: number; genesisHash: string; +} | { + kind: "hopConnectStart"; + connId: number; + genesisHash: string; + endpoint: string; } | { kind: "chainSend"; connId: number; diff --git a/vendor/truapi-host/dist/worker-protocol.js b/vendor/truapi-host/dist/worker-protocol.js index de60eb7e7..f59f811b7 100644 --- a/vendor/truapi-host/dist/worker-protocol.js +++ b/vendor/truapi-host/dist/worker-protocol.js @@ -28,6 +28,12 @@ // transferables: the sender keeps using its buffer (the worker side posts // views into WASM memory) and frames are small, so the copy is the simpler // safe choice. +/** Shared cap includes connections still opening or closing during an open. */ +export const MAX_JSON_RPC_CONNECTIONS = 64; +/** Wallet custody belongs to the runtime, never a product-specific callback bundle. */ +export const COINAGE_WALLET_CALLBACKS = { + nativeCoinage: true, +}; /** * Is `url` a `ws://` URL on a loopback host? The tap forwards every frame * verbatim, key material included, and redacts nothing, so loopback is the whole diff --git a/vendor/truapi-host/dist/worker-runtime.js b/vendor/truapi-host/dist/worker-runtime.js index 468620586..ae3cc330f 100644 --- a/vendor/truapi-host/dist/worker-runtime.js +++ b/vendor/truapi-host/dist/worker-runtime.js @@ -4,6 +4,7 @@ // state that needs DOM access (localStorage, prompts) while the core dispatcher // runs here off the page main thread. import { isLoopbackWsUrl } from "./worker-protocol.js"; +import { COINAGE_WALLET_CALLBACKS, MAX_JSON_RPC_CONNECTIONS, } from "./worker-protocol.js"; import { TRUAPI_CODEC_VERSION } from "@parity/truapi"; import { createWorkerRawCallbacks, } from "./generated/worker-callbacks.js"; import { handleGetPermissionAuthorizationStatus, handleGetPermissionAuthorizationStatuses, handleSetPermissionAuthorizationStatus, } from "./worker-permission-authorization.js"; @@ -30,7 +31,11 @@ const subscriptionListeners = new Map(); let nextConnId = 0; const chainConnectAcks = new Map(); const chainResponseListeners = new Map(); +const chainCloseListeners = new Map(); +let connectionsDisposed = false; function callbackRequest(name, args, coreId) { + if (connectionsDisposed) + return Promise.reject(new Error("Host runtime is unavailable")); return new Promise((resolve, reject) => { const requestId = ++nextRequestId; pendingCallbacks.set(requestId, (r) => { @@ -39,30 +44,48 @@ function callbackRequest(name, args, coreId) { else reject(new Error(r.error)); }); - postToMain({ - kind: "callbackRequest", - requestId, - name, - args, - ...(coreId === undefined ? {} : { coreId }), - }); + try { + postToMain({ + kind: "callbackRequest", + requestId, + name, + args, + ...(coreId === undefined ? {} : { coreId }), + }); + } + catch { + pendingCallbacks.delete(requestId); + reject(new Error("Host callback transport is unavailable")); + } }); } function startSubscription(name, payload, sendItem, sendError, coreId) { + if (connectionsDisposed) { + sendError({ reason: "Host runtime is unavailable" }); + return () => { }; + } const subId = ++nextSubId; subscriptionListeners.set(subId, { sendItem: sendItem, sendError: (error) => sendError({ reason: error }), }); - postToMain({ - kind: "subscriptionStart", - subId, - name, - payload, - ...(coreId === undefined ? {} : { coreId }), - }); - return () => { + try { + postToMain({ + kind: "subscriptionStart", + subId, + name, + payload, + ...(coreId === undefined ? {} : { coreId }), + }); + } + catch { subscriptionListeners.delete(subId); + sendError({ reason: "Host subscription transport is unavailable" }); + return () => { }; + } + return () => { + if (!subscriptionListeners.delete(subId)) + return; postToMain({ kind: "subscriptionStop", subId }); }; } @@ -93,36 +116,87 @@ function startSubscription(name, payload, sendItem, sendError, coreId) { * `close` posts `chainClose`, and every `chainResponse` for this `connId` is * delivered to `onResponse`. */ -function chainConnect(genesisHash, onResponse) { - const connId = ++nextConnId; - return new Promise((resolve, reject) => { - chainConnectAcks.set(connId, (ack) => { - if (!ack.ok) { - chainResponseListeners.delete(connId); - reject(new Error(ack.error)); - return; - } - resolve({ - send(request) { - postToMain({ kind: "chainSend", connId, request }); - }, - close() { - chainResponseListeners.delete(connId); - postToMain({ kind: "chainClose", connId }); - }, +function chainConnect(genesisHash, onResponse, onClosed) { + return connectRpc({ kind: "chainConnectStart", genesisHash }, onResponse, onClosed); +} +function hopConnect(genesisHash, endpoint, onResponse, onClosed) { + return connectRpc({ kind: "hopConnectStart", genesisHash, endpoint }, onResponse, onClosed); +} +function closeRpcConnection(connId, notify = true) { + const ack = chainConnectAcks.get(connId); + const onClosed = chainCloseListeners.get(connId); + chainConnectAcks.delete(connId); + chainResponseListeners.delete(connId); + chainCloseListeners.delete(connId); + ack?.({ ok: false, error: "JSON-RPC connection closed before opening" }); + if (notify) { + try { + onClosed?.(); + } + catch { + postToMain({ + kind: "disposeError", + error: "JSON-RPC close callback failed", }); + } + } +} +function connectRpc(start, onResponse, onClosed) { + if (connectionsDisposed || + chainCloseListeners.size >= MAX_JSON_RPC_CONNECTIONS) { + return Promise.reject(new Error("JSON-RPC connections unavailable or limit reached")); + } + const connId = ++nextConnId; + const { promise, resolve, reject } = Promise.withResolvers(); + chainConnectAcks.set(connId, (ack) => { + if (!ack.ok) { + chainResponseListeners.delete(connId); + chainCloseListeners.delete(connId); + reject(new Error(ack.error)); + return; + } + resolve({ + send(request) { + if (!chainCloseListeners.has(connId)) { + throw new Error("JSON-RPC connection is closed"); + } + postToMain({ kind: "chainSend", connId, request }); + }, + close() { + if (!chainCloseListeners.has(connId)) + return; + closeRpcConnection(connId, false); + postToMain({ kind: "chainClose", connId }); + }, }); - chainResponseListeners.set(connId, onResponse); - postToMain({ kind: "chainConnectStart", connId, genesisHash }); }); + chainCloseListeners.set(connId, onClosed); + chainResponseListeners.set(connId, (json) => { + try { + onResponse(json); + } + catch (err) { + closeRpcConnection(connId); + throw err; + } + }); + try { + postToMain({ ...start, connId }); + } + catch (err) { + closeRpcConnection(connId, false); + reject(err); + } + return promise; } /** Build the host-level callback object passed to the WASM runtime. */ function buildRawCallbacks(capabilities, coreId) { return { ...createWorkerRawCallbacks({ - callbackRequest: (name, args) => callbackRequest(name, args, coreId), + callbackRequest: (name, args) => callbackRequest(name, args, COINAGE_WALLET_CALLBACKS[name] ? undefined : coreId), startSubscription: (name, payload, sendItem, sendError) => startSubscription(name, payload, sendItem, sendError, coreId), chainConnect, + hopConnect, }, capabilities), /** * Demand on a product's worker crossed zero. Every transition arrives @@ -498,6 +572,41 @@ const identityOperations = new Set(); let allowanceNetworkSuffix = null; let allowanceGeneration = 0; const allowanceOperations = new Set(); +const nativeChatContactsOperations = new Set(); +function handleNativeChatContacts(requestId) { + const rt = runtime; + const generation = allowanceGeneration; + const operation = (async () => { + try { + if (!rt || !isSigningRuntime(rt)) { + throw new Error("native Chat contacts are unsupported on a pairing host"); + } + const activation = rt.localIdentityContext().activationId; + const snapshot = await rt.getNativeChatContacts(); + if (runtime !== rt || + generation !== allowanceGeneration || + rt.localIdentityContext().activationId !== activation) { + throw new Error("local identity activation changed"); + } + postToMain({ + kind: "nativeChatContactsResponse", + requestId, + ok: true, + snapshot, + }); + } + catch (error) { + postToMain({ + kind: "nativeChatContactsResponse", + requestId, + ok: false, + error: errorMessage(error), + }); + } + })(); + nativeChatContactsOperations.add(operation); + void operation.finally(() => nativeChatContactsOperations.delete(operation)); +} function handleWalletAllowanceSnapshot(requestId, input) { const rt = runtime; const generation = allowanceGeneration; @@ -730,6 +839,7 @@ ctx.addEventListener("message", (ev) => { break; } case "activateLocalSession": { + identityAbort?.abort(new Error("local identity activation changed")); const { secret, liteUsername } = msg; void handleSessionActivation(msg.requestId, "activateLocalSession", (rt) => { const signing = rt; @@ -797,6 +907,9 @@ ctx.addEventListener("message", (ev) => { case "getWalletAllowanceSnapshot": handleWalletAllowanceSnapshot(msg.requestId, msg.productIds); break; + case "getNativeChatContacts": + handleNativeChatContacts(msg.requestId); + break; case "getPermissionAuthorizationStatus": void handleGetPermissionAuthorizationStatus(runtime, postToMain, msg.productId, msg.requestId, msg.request); break; @@ -830,12 +943,18 @@ ctx.addEventListener("message", (ev) => { chainConnectAcks.delete(msg.connId); cb(msg.ok ? { ok: true } : { ok: false, error: msg.error }); } + else if (msg.ok) { + postToMain({ kind: "chainClose", connId: msg.connId }); + } break; } case "chainResponse": { dispatchChainResponse(msg.connId, msg.json, chainResponseListeners, postToMain); break; } + case "chainClosed": + closeRpcConnection(msg.connId); + break; case "publishChatAction": handlePublishAction(CHAT_ACTION_ENTRY_POINT, cores.get(msg.coreId), postToMain, msg.coreId, msg.requestId, msg.action); break; @@ -859,12 +978,22 @@ ctx.addEventListener("message", (ev) => { runtime = null; allowanceGeneration++; identityAbort?.abort(new Error("runtime disposed")); + connectionsDisposed = true; + for (const settle of pendingCallbacks.values()) { + settle({ ok: false, error: "Host runtime is unavailable" }); + } + pendingCallbacks.clear(); + for (const connId of chainCloseListeners.keys()) { + closeRpcConnection(connId); + postToMain({ kind: "chainClose", connId }); + } void (async () => { try { if (disposing && isSigningRuntime(disposing)) await disposing.disconnectSession(); await Promise.allSettled(identityOperations); await Promise.allSettled(allowanceOperations); + await Promise.allSettled(nativeChatContactsOperations); await Promise.all([...cores.keys()].map((coreId) => disposeCore(coreId))); disposing?.free(); } diff --git a/vendor/truapi-host/package.json b/vendor/truapi-host/package.json index 9cd791175..115ef1acd 100644 --- a/vendor/truapi-host/package.json +++ b/vendor/truapi-host/package.json @@ -2,7 +2,7 @@ "name": "@parity/truapi-host", "version": "0.23.0", "description": "WASM-backed TrUAPI host runtime: embeds the Rust core, with web iframe and Web Worker entry points", - "license": "MIT", + "license": "MIT AND AGPL-3.0-only", "author": "Parity Technologies ", "repository": { "type": "git", @@ -76,7 +76,9 @@ "!dist/**/*.wasm.gz", "!dist/**/*.wasm.br", "README.md", - "LICENSE" + "LICENSE", + "LICENSE-AGPL-3.0", + "NOTICE" ], "scripts": { "build": "tsc -b && node scripts/build-cjs.mjs", diff --git a/vendor/truapi/dist/client.js b/vendor/truapi/dist/client.js index 2867a4bc1..2e2e4cfcf 100644 --- a/vendor/truapi/dist/client.js +++ b/vendor/truapi/dist/client.js @@ -7,11 +7,12 @@ import * as W from "./generated/wire-table.js"; // Every method's request/response (or start/stop/interrupt/receive) frames // share one (trait, method) address: which leg of the exchange a frame // carries is the wire's own `messageType` byte, not part of the address. A -// late or duplicate *answer*-leg frame (Response/Stop/Interrupt/Receive) for -// a known method can legitimately arrive with no matching pending call or -// subscription (e.g. after a request already timed out, or after -// `unsubscribe`), so those are ignored rather than reported as a protocol -// violation. A *request*-leg frame (Request/Start) with nothing to route to +// late or duplicate *answer*-leg frame for a known method can legitimately +// arrive with no matching pending call or subscription: a Stop/Interrupt/ +// Receive after `unsubscribe`, or a Response to a request that already timed +// out. Those are ignored rather than reported as a protocol violation; a +// Response to a request this side never sent is still reported. A +// *request*-leg frame (Request/Start) with nothing to route to // is never expected — it means this build genuinely doesn't implement the // pair (no client was ever created, or the specific host-initiated method // has no registration) — so it still earns the same reply as an unknown @@ -140,6 +141,10 @@ export function createTransport(provider, options = {}) { const requestIdPrefix = options.requestIdPrefix ?? "p:"; let closedError = null; const pending = new Map(); + // Sent requests abandoned at their deadline, oldest first. A response for + // one of these is a normal late answer; any other unmatched response is not. + const abandoned = new Set(); + const MAX_ABANDONED = 256; const subscriptions = new Map(); // Keyed by the full (trait, method) pair: a bare method id would collide // the moment two traits both number a subscription the same. @@ -413,12 +418,23 @@ export function createTransport(provider, options = {}) { return; } if (KNOWN_WIRE_IDS.has(`${payload.traitId}:${payload.methodId}`)) { + if (payload.messageType === MESSAGE_TYPE_RESPONSE) { + // A late answer to a request this side abandoned at its deadline is + // normal, as is one for another transport sharing the connection or a + // pending request whose mismatch is reported above. A response to a + // request this transport never sent is not. + const ours = requestId.startsWith(requestIdPrefix); + if (ours && !pending.has(requestId) && !abandoned.delete(requestId)) { + reportProtocolViolation(`ignoring response for request ${requestId} on (${payload.traitId}, ${payload.methodId}): no such request was sent`); + } + return; + } if (payload.messageType === MESSAGE_TYPE_STOP || payload.messageType === MESSAGE_TYPE_INTERRUPT || payload.messageType === MESSAGE_TYPE_RECEIVE) { - // A known method's answer-leg frame (Response/Stop/Interrupt/ - // Receive) with nothing to route to: a normal late/stale frame, not - // a protocol violation. + // A known method's subscription-leg frame (Stop/Interrupt/Receive) + // with nothing to route to: a normal late/stale frame, not a + // protocol violation. return; } if (payload.messageType !== MESSAGE_TYPE_REQUEST) { @@ -623,8 +639,13 @@ export function createTransport(provider, options = {}) { // The host is told even though this side has stopped waiting: a // deadline that only rejects locally is exactly the leak the // `Cancel` leg exists to close. - if (entry.sent) + if (entry.sent) { sendCancel(requestId, ids); + abandoned.add(requestId); + if (abandoned.size > MAX_ABANDONED) { + abandoned.delete(abandoned.values().next().value); + } + } reject(isHandshake ? new Error(`TrUAPI handshake timed out after ${HANDSHAKE_TIMEOUT_MS}ms; the host did not answer on wire codec ${TRUAPI_CODEC_VERSION}`) : new RequestTimeoutError(requestId, ids.trait, ids.method, timeoutMs)); diff --git a/vendor/truapi/dist/explorer/codegen/types.js b/vendor/truapi/dist/explorer/codegen/types.js index aa5d7a74f..9de73d4e6 100644 --- a/vendor/truapi/dist/explorer/codegen/types.js +++ b/vendor/truapi/dist/explorer/codegen/types.js @@ -27,7 +27,7 @@ export const types = [ id: "allocatable-resource", name: "AllocatableResource", category: "resource_allocation", - definition: 'export type AllocatableResource =\n | { tag: "StatementStoreAllowance"; value?: undefined }\n | { tag: "BulletinAllowance"; value?: undefined }\n | { tag: "SmartContractAllowance"; value: DerivationIndex }\n | { tag: "AutoSigning"; value?: undefined }\n;', + definition: 'export type AllocatableResource =\n | { tag: "StatementStoreAllowance"; value?: undefined }\n | { tag: "BulletinAllowance"; value?: undefined }\n | { tag: "SmartContractAllowance"; value: DerivationIndex }\n | { tag: "AutoSigning"; value?: undefined }\n | { tag: "ProductStatementStoreAllowance"; value: DerivationIndex }\n;', description: "A resource the host can pre-allocate on behalf of the product (RFC 0010).\n\nFor the slot-table allowances (`StatementStoreAllowance`,\n`BulletinAllowance`, `SmartContractAllowance`), pre-allocation is\nopportunistic and the host may also fulfil the allowance implicitly on the\nfirst submission. `AutoSigning` must be requested explicitly through this\ncall.", variants: [ { @@ -50,6 +50,11 @@ export const types = [ type: '{ tag: "AutoSigning"; value?: undefined }', description: "Permission to sign on the product's behalf without per-call user prompts.", }, + { + name: "ProductStatementStoreAllowance", + type: '{ tag: "ProductStatementStoreAllowance"; value: DerivationIndex }', + description: "Current UTC-day Statement Store allowance whose target is the product\naccount selected by this derivation index.", + }, ], }, { @@ -2484,107 +2489,789 @@ export const types = [ ], }, { - id: "host-local-storage-write-request", - name: "HostLocalStorageWriteRequest", - category: "local_storage", - definition: "export interface HostLocalStorageWriteRequest {\n key: string;\n value: HexString;\n}", - description: "Request to write a value into local storage.", + id: "host-local-storage-write-request", + name: "HostLocalStorageWriteRequest", + category: "local_storage", + definition: "export interface HostLocalStorageWriteRequest {\n key: string;\n value: HexString;\n}", + description: "Request to write a value into local storage.", + fields: [ + { + name: "key", + type: "string", + description: "Storage key to write.", + }, + { + name: "value", + type: "HexString", + description: "Value to store at the key.", + }, + ], + }, + { + id: "host-locale-localize-timestamps-request", + name: "HostLocaleLocalizeTimestampsRequest", + category: "locale", + definition: "export interface HostLocaleLocalizeTimestampsRequest {\n timestampsMs: Array;\n languageTag: string;\n timeZone: string;\n}", + description: "Convert UTC instants using a snapshot of the host's locale subscription.", + fields: [ + { + name: "timestamps_ms", + type: "Array", + description: "At most 128 Unix millisecond instants, no later than year 9999.", + }, + { + name: "language_tag", + type: "string", + description: "Language tag from the locale subscription, not a guessed language.", + }, + { + name: "time_zone", + type: "string", + description: "Time zone from the locale subscription; evaluated separately at each instant.", + }, + ], + }, + { + id: "host-locale-localize-timestamps-response", + name: "HostLocaleLocalizeTimestampsResponse", + category: "locale", + definition: "export interface HostLocaleLocalizeTimestampsResponse {\n timestamps: Array;\n}", + description: "Local timestamps in exactly the request's order.", + fields: [ + { + name: "timestamps", + type: "Array", + description: "One result per requested timestamp; partial success is not returned.", + }, + ], + }, + { + id: "host-locale-localized-timestamp", + name: "HostLocaleLocalizedTimestamp", + category: "locale", + definition: "export interface HostLocaleLocalizedTimestamp {\n localDate: string;\n time: string;\n date: string;\n dateTime: string;\n}", + description: "One timestamp's calendar identity and presentation in the requested context.", + fields: [ + { + name: "local_date", + type: "string", + description: "Gregorian YYYY-MM-DD local date, independent of display language/calendar.", + }, + { + name: "time", + type: "string", + description: "Localized short time, including the host language's hour-cycle convention.", + }, + { + name: "date", + type: "string", + description: "Localized date label.", + }, + { + name: "date_time", + type: "string", + description: "Localized date and time with a time-zone indication for detail views.", + }, + ], + }, + { + id: "host-locale-subscribe-item", + name: "HostLocaleSubscribeItem", + category: "locale", + definition: "export interface HostLocaleSubscribeItem {\n languageTag: string;\n timeZone?: string;\n}", + description: "Host language and local time zone, replaced together when either changes.", + fields: [ + { + name: "language_tag", + type: "string", + description: "BCP 47 language tag selected by the host.", + }, + { + name: "time_zone", + type: "string | undefined", + description: "IANA time zone, or absent when the host cannot supply local time.", + }, + ], + }, + { + id: "host-native-chat-acknowledgment", + name: "HostNativeChatAcknowledgment", + category: "account", + definition: "export interface HostNativeChatAcknowledgment {\n peerIdentity: HexString;\n requestId: string;\n responseCode: number;\n}", + description: "A peer's native delivery acknowledgment, not a payment-clearing receipt.", + fields: [ + { + name: "peer_identity", + type: "HexString", + description: "Authenticated acknowledging identity.", + }, + { + name: "request_id", + type: "string", + description: "Acknowledged native request identifier.", + }, + { + name: "response_code", + type: "number", + description: "Native response code; zero denotes successful delivery processing.", + }, + ], + }, + { + id: "host-native-chat-attachment", + name: "HostNativeChatAttachment", + category: "account", + definition: "export interface HostNativeChatAttachment {\n attachmentId: HexString;\n metadata: HostNativeChatAttachmentMetadata;\n state: HostNativeChatAttachmentState;\n}", + description: "Public attachment handle; only the Host can resolve its private backing.", + fields: [ + { + name: "attachment_id", + type: "HexString", + description: "Opaque handle scoped to the current wallet, network and calling product.", + }, + { + name: "metadata", + type: "HostNativeChatAttachmentMetadata", + description: "Non-secret native metadata.", + }, + { + name: "state", + type: "HostNativeChatAttachmentState", + description: "Current durable transfer progress.", + }, + ], + }, + { + id: "host-native-chat-attachment-kind", + name: "HostNativeChatAttachmentKind", + category: "account", + definition: 'export type HostNativeChatAttachmentKind =\n | { tag: "File"; value?: undefined }\n | { tag: "Image"; value: { width: number; height: number; thumbnail?: HexString } }\n | { tag: "Video"; value: { durationSeconds: number; thumbnail?: HexString } }\n;', + description: "Public native media metadata; thumbnails are BlurHash text, not executable images.", + variants: [ + { + name: "File", + type: '{ tag: "File"; value?: undefined }', + description: "A general document or other opaque file.", + }, + { + name: "Image", + type: '{ tag: "Image"; value: { width: number; height: number; thumbnail?: HexString } }', + description: "An image with native dimensions and an optional UTF-8 BlurHash.", + }, + { + name: "Video", + type: '{ tag: "Video"; value: { durationSeconds: number; thumbnail?: HexString } }', + description: "A video with native duration and an optional UTF-8 BlurHash.", + }, + ], + }, + { + id: "host-native-chat-attachment-metadata", + name: "HostNativeChatAttachmentMetadata", + category: "account", + definition: "export interface HostNativeChatAttachmentMetadata {\n mimeType: string;\n sizeBytes: number;\n kind: HostNativeChatAttachmentKind;\n}", + description: "Safe attachment description, independent of private transfer credentials.", + fields: [ + { + name: "mime_type", + type: "string", + description: "Validated media type; it does not authorize execution or network loading.", + }, + { + name: "size_bytes", + type: "number", + description: "Exact native file size, verified against the downloaded root and chunks.", + }, + { + name: "kind", + type: "HostNativeChatAttachmentKind", + description: "General file, image or video metadata.", + }, + ], + }, + { + id: "host-native-chat-attachment-state", + name: "HostNativeChatAttachmentState", + category: "account", + definition: 'export type HostNativeChatAttachmentState =\n | { tag: "Preparing"; value?: undefined }\n | { tag: "Uploading"; value: { uploadedBytes: number } }\n | { tag: "Downloading"; value: { downloadedBytes: number } }\n | { tag: "Ready"; value?: undefined }\n | { tag: "Recovering"; value?: undefined }\n;', + description: "Durable transfer progress, distinct from message delivery acknowledgment.", + variants: [ + { + name: "Preparing", + type: '{ tag: "Preparing"; value?: undefined }', + description: "The Host is securing an immutable selected source.", + }, + { + name: "Uploading", + type: '{ tag: "Uploading"; value: { uploadedBytes: number } }', + description: "Native HOP entries are being uploaded.", + }, + { + name: "Downloading", + type: '{ tag: "Downloading"; value: { downloadedBytes: number } }', + description: "Verified file bytes are being committed to private local storage.", + }, + { + name: "Ready", + type: '{ tag: "Ready"; value?: undefined }', + description: "Complete verified bytes are available through trusted Host presentation.", + }, + { + name: "Recovering", + type: '{ tag: "Recovering"; value?: undefined }', + description: "An interrupted transfer retains its exact credentials and progress for retry.", + }, + ], + }, + { + id: "host-native-chat-binding", + name: "HostNativeChatBinding", + category: "account", + definition: "export interface HostNativeChatBinding {\n peerIdentity: HexString;\n peerChatPublicKey: HexString;\n identityProof: HexString;\n}", + description: "Peer cryptographic identity independently resolved and bound by the Host.", + fields: [ + { + name: "peer_identity", + type: "HexString", + description: "Authenticated peer root identity.", + }, + { + name: "peer_chat_public_key", + type: "HexString", + description: "Peer identity-level native Chat encryption key.", + }, + { + name: "identity_proof", + type: "HexString", + description: "Identity proof used in the native invitation handshake.", + }, + ], + }, + { + id: "host-native-chat-device", + name: "HostNativeChatDevice", + category: "account", + definition: "export interface HostNativeChatDevice {\n identityAccountId: HexString;\n identityChatPublicKey: HexString;\n productAccount: ProductAccountId;\n accountId: HexString;\n chatPublicKey: HexString;\n}", + description: "The Host-owned device's public identity and statement-signing account.", + fields: [ + { + name: "identity_account_id", + type: "HexString", + description: "Wallet identity on the configured People chain.", + }, + { + name: "identity_chat_public_key", + type: "HexString", + description: "Wallet identity's public X25519 key.", + }, + { + name: "product_account", + type: "ProductAccountId", + description: "Product account used to obtain a statement-store allowance for this device.", + }, + { + name: "account_id", + type: "HexString", + description: "Public statement signer for the Host-owned device.", + }, + { + name: "chat_public_key", + type: "HexString", + description: "Public X25519 key; its secret never leaves the Host.", + }, + ], + }, + { + id: "host-native-chat-invitation", + name: "HostNativeChatInvitation", + category: "account", + definition: "export interface HostNativeChatInvitation {\n invitationId: HexString;\n peerIdentity: HexString;\n username?: string;\n timestamp: bigint;\n text: string;\n}", + description: "An authenticated invitation awaiting the user's Chat decision.", + fields: [ + { + name: "invitation_id", + type: "HexString", + description: "Host-generated stable invitation identifier.", + }, + { + name: "peer_identity", + type: "HexString", + description: "Authenticated sender identity.", + }, + { + name: "username", + type: "string | undefined", + description: "Host-resolved sender username, when available.", + }, + { + name: "timestamp", + type: "bigint", + description: "Authenticated native invitation timestamp in milliseconds.", + }, + { + name: "text", + type: "string", + description: "Ordinary initial text, never an embedded payment or control message.", + }, + ], + }, + { + id: "host-native-chat-messages", + name: "HostNativeChatMessages", + category: "account", + definition: "export interface HostNativeChatMessages {\n peerIdentity: HexString;\n incoming: boolean;\n requestId: string;\n messages: Array;\n}", + description: "Safe ordinary messages from one authenticated native request.", + fields: [ + { + name: "peer_identity", + type: "HexString", + description: "Authenticated counterparty identity.", + }, + { + name: "incoming", + type: "boolean", + description: "Whether the peer sent these messages; false also covers our welcome text.", + }, + { + name: "request_id", + type: "string", + description: "Native request identifier, retained for message-delivery correlation.", + }, + { + name: "messages", + type: "Array", + description: "Native message encodings after custody-sensitive content is removed.", + }, + ], + }, + { + id: "host-native-chat-migration-invitation", + name: "HostNativeChatMigrationInvitation", + category: "account", + definition: "export interface HostNativeChatMigrationInvitation {\n invitationId: HexString;\n requestId: string;\n}", + description: "Native request identity needed to answer a migrated legacy invitation.", + fields: [ + { + name: "invitation_id", + type: "HexString", + description: "Invitation handle in the accompanying legacy public view.", + }, + { + name: "request_id", + type: "string", + description: "Original native request identity to acknowledge when answering.", + }, + ], + }, + { + id: "host-native-chat-open-page", + name: "HostNativeChatOpenPage", + category: "account", + definition: "export interface HostNativeChatOpenPage {\n openId: HexString;\n cursor: number;\n nextCursor?: number;\n}", + description: "Continuation metadata for a bounded page of authenticated incoming plaintext.", + fields: [ + { + name: "open_id", + type: "HexString", + description: "Opaque identifier of the authenticated opening operation.", + }, + { + name: "cursor", + type: "number", + description: "Cursor identifying this page.", + }, + { + name: "next_cursor", + type: "number | undefined", + description: "Cursor to request next; absent when the authenticated batch is complete.", + }, + ], + }, + { + id: "host-native-chat-opened", + name: "HostNativeChatOpened", + category: "account", + definition: "export interface HostNativeChatOpened {\n peerIdentity: HexString;\n senderAccountId: HexString;\n route: HostNativeChatRoute;\n plaintext: HexString;\n}", + description: "Authenticated incoming native plaintext, potentially containing incoming coin keys.", + fields: [ + { + name: "peer_identity", + type: "HexString", + description: "Authenticated peer root identity, never the local wallet's own identity.", + }, + { + name: "sender_account_id", + type: "HexString", + description: "Account that signed the accepted native statement.", + }, + { + name: "route", + type: "HostNativeChatRoute", + description: "Authenticated native context of the incoming statement.", + }, + { + name: "plaintext", + type: "HexString", + description: "Native invitation or tagged request/response plaintext; never outgoing payment memos.", + }, + ], + }, + { + id: "host-native-chat-payment", + name: "HostNativeChatPayment", + category: "account", + definition: "export interface HostNativeChatPayment {\n operationId: HexString;\n requestId: string;\n messageId: string;\n timestamp: bigint;\n peerIdentity: HexString;\n direction: HostNativeChatPaymentDirection;\n amountCents: bigint;\n state: HostNativeChatPaymentState;\n}", + description: "A product-visible payment card; it contains no spendable memo material.", + fields: [ + { + name: "operation_id", + type: "HexString", + description: "Durable, product-scoped operation identifier.", + }, + { + name: "request_id", + type: "string", + description: "Caller request id for outgoing payments; native request id for incoming ones.", + }, + { + name: "message_id", + type: "string", + description: "Native message id used to place the payment in conversation history.", + }, + { + name: "timestamp", + type: "bigint", + description: "Native message timestamp in milliseconds.", + }, + { + name: "peer_identity", + type: "HexString", + description: "Counterparty identity authenticated by the Host.", + }, + { + name: "direction", + type: "HostNativeChatPaymentDirection", + description: "Incoming or outgoing relative to the current wallet.", + }, + { + name: "amount_cents", + type: "bigint", + description: "Exact requested/received value in cents.", + }, + { + name: "state", + type: "HostNativeChatPaymentState", + description: "Durable transport/clearing state.", + }, + ], + }, + { + id: "host-native-chat-payment-direction", + name: "HostNativeChatPaymentDirection", + category: "account", + definition: 'export type HostNativeChatPaymentDirection = "Outgoing" | "Incoming";', + description: "Payment direction relative to the current wallet.", + variants: [ + { + name: "Outgoing", + type: '{ tag: "Outgoing"; value?: undefined }', + description: "An explicitly approved debit from the user's main purse.", + }, + { + name: "Incoming", + type: '{ tag: "Incoming"; value?: undefined }', + description: "A received memo being claimed into the user's main purse.", + }, + ], + }, + { + id: "host-native-chat-payment-failure", + name: "HostNativeChatPaymentFailure", + category: "account", + definition: 'export type HostNativeChatPaymentFailure = "Cancelled" | "InsufficientBalance" | "AlreadySpent" | "InvalidMemo" | "ChainRejected";', + description: "Public, non-secret payment failure categories.", + variants: [ + { + name: "Cancelled", + type: '{ tag: "Cancelled"; value?: undefined }', + description: "No transaction or memo was accepted and the operation was cancelled.", + }, + { + name: "InsufficientBalance", + type: '{ tag: "InsufficientBalance"; value?: undefined }', + description: "The wallet could not fund the approved amount and maximum debit.", + }, + { + name: "AlreadySpent", + type: '{ tag: "AlreadySpent"; value?: undefined }', + description: "Received funds were already spent somewhere other than this claim.", + }, + { + name: "InvalidMemo", + type: '{ tag: "InvalidMemo"; value?: undefined }', + description: "The received memo was invalid for the native Coinage protocol.", + }, + { + name: "ChainRejected", + type: '{ tag: "ChainRejected"; value?: undefined }', + description: "A finalized transaction failed without completing the intended payment.", + }, + ], + }, + { + id: "host-native-chat-payment-state", + name: "HostNativeChatPaymentState", + category: "account", + definition: 'export type HostNativeChatPaymentState =\n | { tag: "Preparing"; value?: undefined }\n | { tag: "Delivering"; value?: undefined }\n | { tag: "Delivered"; value?: undefined }\n | { tag: "Claiming"; value?: undefined }\n | { tag: "PartiallyCleared"; value: { clearedCents: bigint } }\n | { tag: "Cleared"; value?: undefined }\n | { tag: "Recovering"; value?: undefined }\n | { tag: "Failed"; value: { reason: HostNativeChatPaymentFailure } }\n;', + description: "Durable payment state. Delivery and on-chain clearing are deliberately distinct.", + variants: [ + { + name: "Preparing", + type: '{ tag: "Preparing"; value?: undefined }', + description: "Approved inputs are reserved; required split/unload work is in progress.", + }, + { + name: "Delivering", + type: '{ tag: "Delivering"; value?: undefined }', + description: "The encrypted memo is durable and transport delivery is being retried.", + }, + { + name: "Delivered", + type: '{ tag: "Delivered"; value?: undefined }', + description: "The peer acknowledged the memo; settlement has not yet been established.", + }, + { + name: "Claiming", + type: '{ tag: "Claiming"; value?: undefined }', + description: "Received secrets are durably held while their claim is in progress.", + }, + { + name: "PartiallyCleared", + type: '{ tag: "PartiallyCleared"; value: { clearedCents: bigint } }', + description: "Some, but not all, of the payment has been observed clearing on chain.", + }, + { + name: "Cleared", + type: '{ tag: "Cleared"; value?: undefined }', + description: "The complete payment has been verified at chain finality.", + }, + { + name: "Recovering", + type: '{ tag: "Recovering"; value?: undefined }', + description: "An ambiguous effect is retained for reconciliation; inputs remain reserved.", + }, + { + name: "Failed", + type: '{ tag: "Failed"; value: { reason: HostNativeChatPaymentFailure } }', + description: "A definitive failure; the Host has reconciled any possible prior effects.", + }, + ], + }, + { + id: "host-native-chat-peer", + name: "HostNativeChatPeer", + category: "account", + definition: "export interface HostNativeChatPeer {\n identityAccountId: HexString;\n username?: string;\n devices: Array;\n incomingChannels: Array;\n readyForPayments: boolean;\n}", + description: "Public conversation state; products cannot write this roster back to the Host.", + fields: [ + { + name: "identity_account_id", + type: "HexString", + description: "Recipient wallet identity.", + }, + { + name: "username", + type: "string | undefined", + description: "Username resolved by the Host, if currently available.", + }, + { + name: "devices", + type: "Array", + description: "Devices admitted by authenticated native invitation/control messages.", + }, + { + name: "incoming_channels", + type: "Array", + description: "Native session topics for subscriptions, not request/response channel hashes.", + }, + { + name: "ready_for_payments", + type: "boolean", + description: "Whether establishment and legacy-device revocation have been acknowledged.", + }, + ], + }, + { + id: "host-native-chat-peer-device", + name: "HostNativeChatPeerDevice", + category: "account", + definition: "export interface HostNativeChatPeerDevice {\n accountId: HexString;\n chatPublicKey: HexString;\n}", + description: "Public metadata for one authenticated remote device.", + fields: [ + { + name: "account_id", + type: "HexString", + description: "Remote device's statement signer.", + }, + { + name: "chat_public_key", + type: "HexString", + description: "Remote device's authenticated public X25519 key.", + }, + ], + }, + { + id: "host-native-chat-prepared", + name: "HostNativeChatPrepared", + category: "account", + definition: "export interface HostNativeChatPrepared {\n statement: SignedStatement;\n peerIdentity: HexString;\n requestId: string;\n requiresAck: boolean;\n clientRequestId?: string;\n}", + description: "Signed ciphertext with the native identity required for durable product delivery.", fields: [ { - name: "key", - type: "string", - description: "Storage key to write.", + name: "statement", + type: "SignedStatement", + description: "Exact signed ciphertext to submit again when retrying delivery.", }, { - name: "value", + name: "peer_identity", type: "HexString", - description: "Value to store at the key.", + description: "Authenticated recipient root identity.", + }, + { + name: "request_id", + type: "string", + description: "Native request identity used to correlate delivery acknowledgments.", + }, + { + name: "requires_ack", + type: "boolean", + description: "Whether delivery remains pending until a native peer acknowledgment arrives.", + }, + { + name: "client_request_id", + type: "string | undefined", + description: "Original product intent id for correlating migrated pending UI, when retained.", }, ], }, { - id: "host-locale-localize-timestamps-request", - name: "HostLocaleLocalizeTimestampsRequest", - category: "locale", - definition: "export interface HostLocaleLocalizeTimestampsRequest {\n timestampsMs: Array;\n languageTag: string;\n timeZone: string;\n}", - description: "Convert UTC instants using a snapshot of the host's locale subscription.", + id: "host-native-chat-rich-message", + name: "HostNativeChatRichMessage", + category: "account", + definition: "export interface HostNativeChatRichMessage {\n peerIdentity: HexString;\n incoming: boolean;\n requestId: string;\n messageId: string;\n timestamp: bigint;\n kind: HostNativeChatRichMessageKind;\n text?: string;\n attachments: Array;\n}", + description: "Authenticated rich content after private file capabilities have been removed.", fields: [ { - name: "timestamps_ms", - type: "Array", - description: "At most 128 Unix millisecond instants, no later than year 9999.", + name: "peer_identity", + type: "HexString", + description: "Authenticated conversation identity.", }, { - name: "language_tag", + name: "incoming", + type: "boolean", + description: "Whether the remote peer authored this content.", + }, + { + name: "request_id", type: "string", - description: "Language tag from the locale subscription, not a guessed language.", + description: "Native request id used for delivery acknowledgment.", }, { - name: "time_zone", + name: "message_id", type: "string", - description: "Time zone from the locale subscription; evaluated separately at each instant.", + description: "Native id of this message or edit event.", + }, + { + name: "timestamp", + type: "bigint", + description: "Native timestamp in milliseconds.", + }, + { + name: "kind", + type: "HostNativeChatRichMessageKind", + description: "New message, reply or edit; authorship checks still apply to edits.", + }, + { + name: "text", + type: "string | undefined", + description: "Ordinary optional text.", + }, + { + name: "attachments", + type: "Array", + description: "Opaque file handles and safe metadata, never native file references.", }, ], }, { - id: "host-locale-localize-timestamps-response", - name: "HostLocaleLocalizeTimestampsResponse", - category: "locale", - definition: "export interface HostLocaleLocalizeTimestampsResponse {\n timestamps: Array;\n}", - description: "Local timestamps in exactly the request's order.", - fields: [ + id: "host-native-chat-rich-message-kind", + name: "HostNativeChatRichMessageKind", + category: "account", + definition: 'export type HostNativeChatRichMessageKind =\n | { tag: "Message"; value?: undefined }\n | { tag: "Reply"; value: { messageId: string } }\n | { tag: "Edited"; value: { messageId: string } }\n;', + description: "Native rich-content timeline operation.", + variants: [ { - name: "timestamps", - type: "Array", - description: "One result per requested timestamp; partial success is not returned.", + name: "Message", + type: '{ tag: "Message"; value?: undefined }', + description: "A new ordinary rich message.", + }, + { + name: "Reply", + type: '{ tag: "Reply"; value: { messageId: string } }', + description: "A new rich message replying to an earlier message.", + }, + { + name: "Edited", + type: '{ tag: "Edited"; value: { messageId: string } }', + description: "A replacement of the same author's earlier rich content.", }, ], }, { - id: "host-locale-localized-timestamp", - name: "HostLocaleLocalizedTimestamp", - category: "locale", - definition: "export interface HostLocaleLocalizedTimestamp {\n localDate: string;\n time: string;\n date: string;\n dateTime: string;\n}", - description: "One timestamp's calendar identity and presentation in the requested context.", - fields: [ - { - name: "local_date", - type: "string", - description: "Gregorian YYYY-MM-DD local date, independent of display language/calendar.", - }, + id: "host-native-chat-route", + name: "HostNativeChatRoute", + category: "account", + definition: 'export type HostNativeChatRoute = "Invitation" | "Identity" | "Device";', + description: "The authenticated native encryption and statement-routing context.", + variants: [ { - name: "time", - type: "string", - description: "Localized short time, including the host language's hour-cycle convention.", + name: "Invitation", + type: '{ tag: "Invitation"; value?: undefined }', + description: "A native invitation addressed to a peer identity.", }, { - name: "date", - type: "string", - description: "Localized date label.", + name: "Identity", + type: '{ tag: "Identity"; value?: undefined }', + description: "Native identity transport used for establishment and device admission.", }, { - name: "date_time", - type: "string", - description: "Localized date and time with a time-zone indication for detail views.", + name: "Device", + type: '{ tag: "Device"; value?: undefined }', + description: "Native transport between admitted Chat devices.", }, ], }, { - id: "host-locale-subscribe-item", - name: "HostLocaleSubscribeItem", - category: "locale", - definition: "export interface HostLocaleSubscribeItem {\n languageTag: string;\n timeZone?: string;\n}", - description: "Host language and local time zone, replaced together when either changes.", + id: "host-native-chat-state-page", + name: "HostNativeChatStatePage", + category: "account", + definition: "export interface HostNativeChatStatePage {\n stateId: HexString;\n cursor: number;\n nextCursor?: number;\n}", + description: "Continuation metadata for a bounded page of a stable public state snapshot.", fields: [ { - name: "language_tag", - type: "string", - description: "BCP 47 language tag selected by the host.", + name: "state_id", + type: "HexString", + description: "Opaque identifier of the Host-retained public state snapshot.", }, { - name: "time_zone", - type: "string | undefined", - description: "IANA time zone, or absent when the host cannot supply local time.", + name: "cursor", + type: "number", + description: "Cursor identifying this page.", + }, + { + name: "next_cursor", + type: "number | undefined", + description: "Cursor to request next; absent when the snapshot is complete.", }, ], }, @@ -2926,6 +3613,233 @@ export const types = [ }, ], }, + { + id: "host-product-device-chat-error", + name: "HostProductDeviceChatError", + category: "account", + definition: 'export type HostProductDeviceChatError = "NotConnected" | "AccessNotGranted" | "UserRejected" | "AllowanceRequired" | "PeerNotReady" | "OperationConflict" | "InvalidRequest" | "InvalidStatement" | "RecipientNotFound" | "InsufficientBalance" | "StorageUnavailable" | "NetworkUnavailable" | "OperationNotFound" | "AttachmentsUnavailable";', + description: "Failure of a Host-owned Chat operation before a public update is available.", + variants: [ + { + name: "NotConnected", + type: '{ tag: "NotConnected"; value?: undefined }', + description: "There is no current authenticated wallet session.", + }, + { + name: "AccessNotGranted", + type: '{ tag: "AccessNotGranted"; value?: undefined }', + description: "The calling product lacks the required Chat or transport capability.", + }, + { + name: "UserRejected", + type: '{ tag: "UserRejected"; value?: undefined }', + description: "The user declined a Host-mediated review, selection or export.", + }, + { + name: "AllowanceRequired", + type: '{ tag: "AllowanceRequired"; value?: undefined }', + description: "The device still needs its statement-store allowance.", + }, + { + name: "PeerNotReady", + type: '{ tag: "PeerNotReady"; value?: undefined }', + description: "The recipient has not completed authenticated establishment/revocation.", + }, + { + name: "OperationConflict", + type: '{ tag: "OperationConflict"; value?: undefined }', + description: "An id was reused with different immutable operation parameters.", + }, + { + name: "InvalidRequest", + type: '{ tag: "InvalidRequest"; value?: undefined }', + description: "The proposed request violates native bounds or message policy.", + }, + { + name: "InvalidStatement", + type: '{ tag: "InvalidStatement"; value?: undefined }', + description: "An incoming statement failed native authentication or decryption.", + }, + { + name: "RecipientNotFound", + type: '{ tag: "RecipientNotFound"; value?: undefined }', + description: "The configured network could not resolve the requested identity.", + }, + { + name: "InsufficientBalance", + type: '{ tag: "InsufficientBalance"; value?: undefined }', + description: "The main purse cannot fund the proposed payment.", + }, + { + name: "StorageUnavailable", + type: '{ tag: "StorageUnavailable"; value?: undefined }', + description: "Durable storage could not safely commit the operation.", + }, + { + name: "NetworkUnavailable", + type: '{ tag: "NetworkUnavailable"; value?: undefined }', + description: "The configured chain or statement-store service is unavailable.", + }, + { + name: "OperationNotFound", + type: '{ tag: "OperationNotFound"; value?: undefined }', + description: "The requested operation does not belong to the calling product.", + }, + { + name: "AttachmentsUnavailable", + type: '{ tag: "AttachmentsUnavailable"; value?: undefined }', + description: "This Host cannot select, recover or present the requested private file.", + }, + ], + }, + { + id: "host-product-device-chat-request", + name: "HostProductDeviceChatRequest", + category: "account", + definition: 'export type HostProductDeviceChatRequest =\n | { tag: "Initialize"; value?: undefined }\n | { tag: "Bind"; value: { username: string } }\n | { tag: "Prepare"; value: { peerIdentity: HexString; route: HostNativeChatRoute; plaintext: HexString } }\n | { tag: "Open"; value: { statement: SignedStatement } }\n | { tag: "SendPayment"; value: { peerIdentity: HexString; requestId: string; amountCents: bigint } }\n | { tag: "PaymentStatus"; value: { operationId: HexString } }\n | { tag: "ReconcilePayments"; value?: undefined }\n | { tag: "PrepareAttachments"; value: { peerIdentity: HexString; requestId: string; text?: string } }\n | { tag: "OpenAttachment"; value: { attachmentId: HexString } }\n | { tag: "CommitMigration"; value: { migrationId: HexString } }\n | { tag: "ContinueOpen"; value: { openId: HexString; cursor: number } }\n | { tag: "ContinueState"; value: { stateId: HexString; cursor: number } }\n | { tag: "PaymentDenomination"; value?: undefined }\n;', + description: "An operation using the calling product's non-exportable Host Chat device.", + variants: [ + { + name: "Initialize", + type: '{ tag: "Initialize"; value?: undefined }', + description: "Restore public metadata, pending ciphertext, and private file-transfer progress.", + }, + { + name: "Bind", + type: '{ tag: "Bind"; value: { username: string } }', + description: "Independently resolve and bind a peer on the trusted network.", + }, + { + name: "Prepare", + type: '{ tag: "Prepare"; value: { peerIdentity: HexString; route: HostNativeChatRoute; plaintext: HexString } }', + description: "Validate native plaintext and return signed ciphertext for product delivery.", + }, + { + name: "Open", + type: '{ tag: "Open"; value: { statement: SignedStatement } }', + description: "Authenticate and decrypt a complete external native statement, never own output.", + }, + { + name: "SendPayment", + type: '{ tag: "SendPayment"; value: { peerIdentity: HexString; requestId: string; amountCents: bigint } }', + description: "Propose one main-purse payment; this operation requires trusted Host review.", + }, + { + name: "PaymentStatus", + type: '{ tag: "PaymentStatus"; value: { operationId: HexString } }', + description: "Read durable payment status without authorizing another spend.", + }, + { + name: "ReconcilePayments", + type: '{ tag: "ReconcilePayments"; value?: undefined }', + description: "Reconcile payment custody and return opaque statements for product delivery.", + }, + { + name: "PrepareAttachments", + type: '{ tag: "PrepareAttachments"; value: { peerIdentity: HexString; requestId: string; text?: string } }', + description: "Select files in trusted Host UI and prepare native rich content without delivery.", + }, + { + name: "OpenAttachment", + type: '{ tag: "OpenAttachment"; value: { attachmentId: HexString } }', + description: "Resume a private download and present or export through trusted Host UI.", + }, + { + name: "CommitMigration", + type: '{ tag: "CommitMigration"; value: { migrationId: HexString } }', + description: "Acknowledge durable product storage of the legacy view and ordinary ciphertext.", + }, + { + name: "ContinueOpen", + type: '{ tag: "ContinueOpen"; value: { openId: HexString; cursor: number } }', + description: "Continue a Host-authenticated incoming batch without supplying new ciphertext.", + }, + { + name: "ContinueState", + type: '{ tag: "ContinueState"; value: { stateId: HexString; cursor: number } }', + description: "Continue a bounded snapshot of custody metadata and pending prepared statements.", + }, + { + name: "PaymentDenomination", + type: '{ tag: "PaymentDenomination"; value?: undefined }', + description: "Read configured raw chain units per native Coinage cent, without spending.", + }, + ], + }, + { + id: "host-product-device-chat-response", + name: "HostProductDeviceChatResponse", + category: "account", + definition: "export interface HostProductDeviceChatResponse {\n device: HostNativeChatDevice;\n peers: Array;\n binding?: HostNativeChatBinding;\n opened: Array;\n prepared: Array;\n payments: Array;\n richMessages: Array;\n migration?: HostProductDeviceChatResponse;\n migrationId?: HexString;\n openPage?: HostNativeChatOpenPage;\n migrationInvitations: Array;\n statePage?: HostNativeChatStatePage;\n coinageCentsUnit?: bigint;\n}", + description: "Cryptographic results and custody metadata; products drive delivery and import.", + fields: [ + { + name: "device", + type: "HostNativeChatDevice", + description: "Public local device metadata, including its allowance account.", + }, + { + name: "peers", + type: "Array", + description: "Host-authenticated peer and device metadata.", + }, + { + name: "binding", + type: "HostNativeChatBinding | undefined", + description: "Newly resolved peer binding, when requested.", + }, + { + name: "opened", + type: "Array", + description: "Authenticated incoming plaintext; incoming payment import is product-owned.", + }, + { + name: "prepared", + type: "Array", + description: "Signed ciphertext for product submission and exact-identity retries.", + }, + { + name: "payments", + type: "Array", + description: "Durable public payment status, never outgoing bearer secrets.", + }, + { + name: "rich_messages", + type: "Array", + description: "Rich-content metadata and trusted private-transfer progress.", + }, + { + name: "migration", + type: "HostProductDeviceChatResponse | undefined", + description: "Legacy public view retained until the product durably commits migration.", + }, + { + name: "migration_id", + type: "HexString | undefined", + description: "Snapshot identifier to acknowledge only after persisting its view and ciphertext.", + }, + { + name: "open_page", + type: "HostNativeChatOpenPage | undefined", + description: "Continuation of an authenticated incoming batch, when opening is paginated.", + }, + { + name: "migration_invitations", + type: "Array", + description: "Native request identities for invitations in the legacy migration view.", + }, + { + name: "state_page", + type: "HostNativeChatStatePage | undefined", + description: "Continuation of a bounded public state snapshot, when metadata is paginated.", + }, + { + name: "coinage_cents_unit", + type: "bigint | undefined", + description: "Configured raw chain units per native Coinage cent, only when requested.\nThis is positive denomination metadata, never a balance or fiat price.", + }, + ], + }, { id: "host-push-notification-cancel-request", name: "HostPushNotificationCancelRequest", @@ -5193,6 +6107,114 @@ export const types = [ }, ], }, + { + id: "v-02-host-product-device-chat-request", + name: "V02HostProductDeviceChatRequest", + category: "account", + definition: 'export type V02HostProductDeviceChatRequest =\n | { tag: "Initialize"; value?: undefined }\n | { tag: "Invite"; value: { username: string; text: string } }\n | { tag: "Receive"; value: { statement: SignedStatement } }\n | { tag: "AcceptInvitation"; value: { invitationId: HexString } }\n | { tag: "RejectInvitation"; value: { invitationId: HexString } }\n | { tag: "Send"; value: { peerIdentity: HexString; requestId: string; messages: Array } }\n | { tag: "SendPayment"; value: { peerIdentity: HexString; requestId: string; amountCents: bigint } }\n | { tag: "PaymentStatus"; value: { operationId: HexString } }\n | { tag: "Reconcile"; value?: undefined }\n | { tag: "SendAttachments"; value: { peerIdentity: HexString; requestId: string; text?: string } }\n | { tag: "OpenAttachment"; value: { attachmentId: HexString } }\n;', + description: "An operation on the calling product's Host-owned native Chat device.", + variants: [ + { + name: "Initialize", + type: '{ tag: "Initialize"; value?: undefined }', + description: "Restore the installation's public device and durable conversation state.", + }, + { + name: "Invite", + type: '{ tag: "Invite"; value: { username: string; text: string } }', + description: "Resolve a username in the configured network and send a fresh invitation.", + }, + { + name: "Receive", + type: '{ tag: "Receive"; value: { statement: SignedStatement } }', + description: "Authenticate, decrypt and durably process a native statement.", + }, + { + name: "AcceptInvitation", + type: '{ tag: "AcceptInvitation"; value: { invitationId: HexString } }', + description: "Accept an invitation previously authenticated and retained by the Host.", + }, + { + name: "RejectInvitation", + type: '{ tag: "RejectInvitation"; value: { invitationId: HexString } }', + description: "Reject an invitation previously authenticated and retained by the Host.", + }, + { + name: "Send", + type: '{ tag: "Send"; value: { peerIdentity: HexString; requestId: string; messages: Array } }', + description: "Send ordinary messages to an established, Host-authenticated peer roster.", + }, + { + name: "SendPayment", + type: '{ tag: "SendPayment"; value: { peerIdentity: HexString; requestId: string; amountCents: bigint } }', + description: "Propose one main-purse payment; this operation always requires Host review.", + }, + { + name: "PaymentStatus", + type: '{ tag: "PaymentStatus"; value: { operationId: HexString } }', + description: "Read a payment's durable status without authorizing another spend.", + }, + { + name: "Reconcile", + type: '{ tag: "Reconcile"; value?: undefined }', + description: "Resume durable transport work and return newly available public views.", + }, + { + name: "SendAttachments", + type: '{ tag: "SendAttachments"; value: { peerIdentity: HexString; requestId: string; text?: string } }', + description: "Select immutable files in trusted Host UI and send native rich content.", + }, + { + name: "OpenAttachment", + type: '{ tag: "OpenAttachment"; value: { attachmentId: HexString } }', + description: "Resume a private download and present or export through trusted Host UI.", + }, + ], + }, + { + id: "v-02-host-product-device-chat-response", + name: "V02HostProductDeviceChatResponse", + category: "account", + definition: "export interface V02HostProductDeviceChatResponse {\n device: HostNativeChatDevice;\n peers: Array;\n invitations: Array;\n messages: Array;\n acknowledgments: Array;\n payments: Array;\n richMessages: Array;\n}", + description: "Public updates from a Host-owned Chat operation.", + fields: [ + { + name: "device", + type: "HostNativeChatDevice", + description: "Public local device metadata, including its allowance account.", + }, + { + name: "peers", + type: "Array", + description: "Current authenticated peers and subscription channels.", + }, + { + name: "invitations", + type: "Array", + description: "Invitations still awaiting a user decision.", + }, + { + name: "messages", + type: "Array", + description: "Newly processed safe ordinary messages.", + }, + { + name: "acknowledgments", + type: "Array", + description: "Newly processed native delivery acknowledgments.", + }, + { + name: "payments", + type: "Array", + description: "Current public payment statuses belonging to the calling product.", + }, + { + name: "rich_messages", + type: "Array", + description: "Safe rich-content views and their current private-transfer progress.", + }, + ], + }, { id: "vertical-alignment", name: "VerticalAlignment", diff --git a/vendor/truapi/dist/generated/client.d.ts b/vendor/truapi/dist/generated/client.d.ts index 076f3a315..ca699c9f5 100644 --- a/vendor/truapi/dist/generated/client.d.ts +++ b/vendor/truapi/dist/generated/client.d.ts @@ -8,7 +8,7 @@ export { ResultAsync, SubscriptionError }; export type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport }; export declare const TRUAPI_VERSION: 2; export declare const TRUAPI_CODEC_VERSION: 3; -export declare const TRUAPI_WIRE_SCHEMA_HASH: "7c073d1a8c5db314"; +export declare const TRUAPI_WIRE_SCHEMA_HASH: "f7be28c22289b365"; /** Account lookup, aliasing, and proof generation. */ export declare class AccountClient { #private; @@ -36,6 +36,29 @@ export declare class AccountClient { listRingVrfKeys(request: T.HostAccountListRingVrfKeysRequest, options?: CallOptions): ResultAsync, S.CallErrorValue>; /** Sign bytes directly with a registered ring-VRF member key. */ ringVrfSign(request: T.HostAccountRingVrfSignRequest, options?: CallOptions): ResultAsync>; + /** + * Use a non-exportable Host Chat device for native cryptographic operations + * and reviewed main-purse payments. The product owns native lifecycle frames, + * subscriptions, delivery, retries, history, and acknowledgments. + * + * `Bind` resolves the peer independently. `Prepare` validates native plaintext + * and returns signed ciphertext for product submission. `Open` authenticates + * complete external statements and rejects reflected local output; it is not + * an arbitrary decryption primitive. Incoming plaintext can contain incoming + * bearer coin keys: persist the import intent securely and use generic payment + * top-up before acknowledging. Wallet/device keys and outgoing main-purse + * coin secrets never leave the Host. + * + * `Initialize` also advances private file transfers. Persist any legacy + * migration view and ordinary prepared statements before `CommitMigration`. + * `ContinueOpen` retrieves the next bounded page of an authenticated batch. + * `ContinueState` retrieves remaining pages of a stable public state snapshot; + * persist every page before committing its migration. + * + * Method 11 (the former raw-crypto interface) and method 12's former V1 actor + * operations are retired, not forwarded. This boundary uses V2 payloads. + */ + deviceChat(request: T.HostProductDeviceChatRequest, options?: CallOptions): ResultAsync>; /** * List non-product accounts the user owns. * diff --git a/vendor/truapi/dist/generated/client.js b/vendor/truapi/dist/generated/client.js index 30ee24651..89b379618 100644 --- a/vendor/truapi/dist/generated/client.js +++ b/vendor/truapi/dist/generated/client.js @@ -7,7 +7,7 @@ import * as W from './wire-table.js'; export { ResultAsync, SubscriptionError }; export const TRUAPI_VERSION = 2; export const TRUAPI_CODEC_VERSION = 3; -export const TRUAPI_WIRE_SCHEMA_HASH = "7c073d1a8c5db314"; +export const TRUAPI_WIRE_SCHEMA_HASH = "f7be28c22289b365"; function toSubscriptionError(error) { if (error instanceof SubscriptionError) return error; @@ -247,6 +247,39 @@ export class AccountClient { }, }); } + /** + * Use a non-exportable Host Chat device for native cryptographic operations + * and reviewed main-purse payments. The product owns native lifecycle frames, + * subscriptions, delivery, retries, history, and acknowledgments. + * + * `Bind` resolves the peer independently. `Prepare` validates native plaintext + * and returns signed ciphertext for product submission. `Open` authenticates + * complete external statements and rejects reflected local output; it is not + * an arbitrary decryption primitive. Incoming plaintext can contain incoming + * bearer coin keys: persist the import intent securely and use generic payment + * top-up before acknowledging. Wallet/device keys and outgoing main-purse + * coin secrets never leave the Host. + * + * `Initialize` also advances private file transfers. Persist any legacy + * migration view and ordinary prepared statements before `CommitMigration`. + * `ContinueOpen` retrieves the next bounded page of an authenticated batch. + * `ContinueState` retrieves remaining pages of a stable public state snapshot; + * persist every page before committing its migration. + * + * Method 11 (the former raw-crypto interface) and method 12's former V1 actor + * operations are retired, not forwarded. This boundary uses V2 payloads. + */ + deviceChat(request, options) { + return this.#transport.request({ + ids: W.ACCOUNT_PRODUCT_DEVICE_CHAT, + payload: T.VersionedHostProductDeviceChatRequest.enc({ tag: "V2", value: request }), + signal: options?.signal, + decodeResponse: (payload) => { + const result = S.Result(T.VersionedHostProductDeviceChatResponse, S.CallError(T.VersionedHostProductDeviceChatError)).dec(payload); + return result.success ? { success: true, value: result.value.value } : result; + }, + }); + } /** * List non-product accounts the user owns. * diff --git a/vendor/truapi/dist/generated/internal-client.d.ts b/vendor/truapi/dist/generated/internal-client.d.ts index 8e05016bf..e08d1ed14 100644 --- a/vendor/truapi/dist/generated/internal-client.d.ts +++ b/vendor/truapi/dist/generated/internal-client.d.ts @@ -7,7 +7,7 @@ export { ResultAsync, SubscriptionError }; export type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport }; export declare const TRUAPI_VERSION: 2; export declare const TRUAPI_CODEC_VERSION: 3; -export declare const TRUAPI_WIRE_SCHEMA_HASH: "7c073d1a8c5db314"; +export declare const TRUAPI_WIRE_SCHEMA_HASH: "f7be28c22289b365"; /** 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 a4cb51f9e..92dbb8fbd 100644 --- a/vendor/truapi/dist/generated/internal-client.js +++ b/vendor/truapi/dist/generated/internal-client.js @@ -7,7 +7,7 @@ import * as W from './wire-table.js'; export { ResultAsync, SubscriptionError }; export const TRUAPI_VERSION = 2; export const TRUAPI_CODEC_VERSION = 3; -export const TRUAPI_WIRE_SCHEMA_HASH = "7c073d1a8c5db314"; +export const TRUAPI_WIRE_SCHEMA_HASH = "f7be28c22289b365"; /** 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 917891f9f..66fa61c14 100644 --- a/vendor/truapi/dist/generated/types.d.ts +++ b/vendor/truapi/dist/generated/types.d.ts @@ -48,6 +48,14 @@ export type AllocatableResource = | { tag: "AutoSigning"; value?: undefined; +} +/** + * Current UTC-day Statement Store allowance whose target is the product + * account selected by this derivation index. + */ + | { + tag: "ProductStatementStoreAllowance"; + value: DerivationIndex; }; export declare const AllocatableResource: S.Codec; /** Outcome of allocating a single resource (RFC 0010). */ @@ -1432,6 +1440,337 @@ export type VersionedHostLocaleSubscribeRequest = value?: undefined; }; export declare const VersionedHostLocaleSubscribeRequest: S.Codec; +/** A peer's native delivery acknowledgment, not a payment-clearing receipt. */ +export interface HostNativeChatAcknowledgment { + /** Authenticated acknowledging identity. */ + peerIdentity: HexString; + /** Acknowledged native request identifier. */ + requestId: string; + /** Native response code; zero denotes successful delivery processing. */ + responseCode: number; +} +export declare const HostNativeChatAcknowledgment: S.Codec; +/** Public attachment handle; only the Host can resolve its private backing. */ +export interface HostNativeChatAttachment { + /** Opaque handle scoped to the current wallet, network and calling product. */ + attachmentId: HexString; + /** Non-secret native metadata. */ + metadata: HostNativeChatAttachmentMetadata; + /** Current durable transfer progress. */ + state: HostNativeChatAttachmentState; +} +export declare const HostNativeChatAttachment: S.Codec; +/** Public native media metadata; thumbnails are BlurHash text, not executable images. */ +export type HostNativeChatAttachmentKind = +/** A general document or other opaque file. */ +{ + tag: "File"; + value?: undefined; +} +/** An image with native dimensions and an optional UTF-8 BlurHash. */ + | { + tag: "Image"; + value: { + width: number; + height: number; + thumbnail?: HexString; + }; +} +/** A video with native duration and an optional UTF-8 BlurHash. */ + | { + tag: "Video"; + value: { + durationSeconds: number; + thumbnail?: HexString; + }; +}; +export declare const HostNativeChatAttachmentKind: S.Codec; +/** Safe attachment description, independent of private transfer credentials. */ +export interface HostNativeChatAttachmentMetadata { + /** Validated media type; it does not authorize execution or network loading. */ + mimeType: string; + /** Exact native file size, verified against the downloaded root and chunks. */ + sizeBytes: number; + /** General file, image or video metadata. */ + kind: HostNativeChatAttachmentKind; +} +export declare const HostNativeChatAttachmentMetadata: S.Codec; +/** Durable transfer progress, distinct from message delivery acknowledgment. */ +export type HostNativeChatAttachmentState = +/** The Host is securing an immutable selected source. */ +{ + tag: "Preparing"; + value?: undefined; +} +/** Native HOP entries are being uploaded. */ + | { + tag: "Uploading"; + value: { + uploadedBytes: number; + }; +} +/** Verified file bytes are being committed to private local storage. */ + | { + tag: "Downloading"; + value: { + downloadedBytes: number; + }; +} +/** Complete verified bytes are available through trusted Host presentation. */ + | { + tag: "Ready"; + value?: undefined; +} +/** An interrupted transfer retains its exact credentials and progress for retry. */ + | { + tag: "Recovering"; + value?: undefined; +}; +export declare const HostNativeChatAttachmentState: S.Codec; +/** Peer cryptographic identity independently resolved and bound by the Host. */ +export interface HostNativeChatBinding { + /** Authenticated peer root identity. */ + peerIdentity: HexString; + /** Peer identity-level native Chat encryption key. */ + peerChatPublicKey: HexString; + /** Identity proof used in the native invitation handshake. */ + identityProof: HexString; +} +export declare const HostNativeChatBinding: S.Codec; +/** The Host-owned device's public identity and statement-signing account. */ +export interface HostNativeChatDevice { + /** Wallet identity on the configured People chain. */ + identityAccountId: HexString; + /** Wallet identity's public X25519 key. */ + identityChatPublicKey: HexString; + /** Product account used to obtain a statement-store allowance for this device. */ + productAccount: ProductAccountId; + /** Public statement signer for the Host-owned device. */ + accountId: HexString; + /** Public X25519 key; its secret never leaves the Host. */ + chatPublicKey: HexString; +} +export declare const HostNativeChatDevice: S.Codec; +/** An authenticated invitation awaiting the user's Chat decision. */ +export interface HostNativeChatInvitation { + /** Host-generated stable invitation identifier. */ + invitationId: HexString; + /** Authenticated sender identity. */ + peerIdentity: HexString; + /** Host-resolved sender username, when available. */ + username?: string; + /** Authenticated native invitation timestamp in milliseconds. */ + timestamp: bigint; + /** Ordinary initial text, never an embedded payment or control message. */ + text: string; +} +export declare const HostNativeChatInvitation: S.Codec; +/** Safe ordinary messages from one authenticated native request. */ +export interface HostNativeChatMessages { + /** Authenticated counterparty identity. */ + peerIdentity: HexString; + /** Whether the peer sent these messages; false also covers our welcome text. */ + incoming: boolean; + /** Native request identifier, retained for message-delivery correlation. */ + requestId: string; + /** Native message encodings after custody-sensitive content is removed. */ + messages: Array; +} +export declare const HostNativeChatMessages: S.Codec; +/** Native request identity needed to answer a migrated legacy invitation. */ +export interface HostNativeChatMigrationInvitation { + /** Invitation handle in the accompanying legacy public view. */ + invitationId: HexString; + /** Original native request identity to acknowledge when answering. */ + requestId: string; +} +export declare const HostNativeChatMigrationInvitation: S.Codec; +/** Continuation metadata for a bounded page of authenticated incoming plaintext. */ +export interface HostNativeChatOpenPage { + /** Opaque identifier of the authenticated opening operation. */ + openId: HexString; + /** Cursor identifying this page. */ + cursor: number; + /** Cursor to request next; absent when the authenticated batch is complete. */ + nextCursor?: number; +} +export declare const HostNativeChatOpenPage: S.Codec; +/** Authenticated incoming native plaintext, potentially containing incoming coin keys. */ +export interface HostNativeChatOpened { + /** Authenticated peer root identity, never the local wallet's own identity. */ + peerIdentity: HexString; + /** Account that signed the accepted native statement. */ + senderAccountId: HexString; + /** Authenticated native context of the incoming statement. */ + route: HostNativeChatRoute; + /** Native invitation or tagged request/response plaintext; never outgoing payment memos. */ + plaintext: HexString; +} +export declare const HostNativeChatOpened: S.Codec; +/** A product-visible payment card; it contains no spendable memo material. */ +export interface HostNativeChatPayment { + /** Durable, product-scoped operation identifier. */ + operationId: HexString; + /** Caller request id for outgoing payments; native request id for incoming ones. */ + requestId: string; + /** Native message id used to place the payment in conversation history. */ + messageId: string; + /** Native message timestamp in milliseconds. */ + timestamp: bigint; + /** Counterparty identity authenticated by the Host. */ + peerIdentity: HexString; + /** Incoming or outgoing relative to the current wallet. */ + direction: HostNativeChatPaymentDirection; + /** Exact requested/received value in cents. */ + amountCents: bigint; + /** Durable transport/clearing state. */ + state: HostNativeChatPaymentState; +} +export declare const HostNativeChatPayment: S.Codec; +/** Payment direction relative to the current wallet. */ +export type HostNativeChatPaymentDirection = "Outgoing" | "Incoming"; +export declare const HostNativeChatPaymentDirection: S.Codec; +/** Public, non-secret payment failure categories. */ +export type HostNativeChatPaymentFailure = "Cancelled" | "InsufficientBalance" | "AlreadySpent" | "InvalidMemo" | "ChainRejected"; +export declare const HostNativeChatPaymentFailure: S.Codec; +/** Durable payment state. Delivery and on-chain clearing are deliberately distinct. */ +export type HostNativeChatPaymentState = +/** Approved inputs are reserved; required split/unload work is in progress. */ +{ + tag: "Preparing"; + value?: undefined; +} +/** The encrypted memo is durable and transport delivery is being retried. */ + | { + tag: "Delivering"; + value?: undefined; +} +/** The peer acknowledged the memo; settlement has not yet been established. */ + | { + tag: "Delivered"; + value?: undefined; +} +/** Received secrets are durably held while their claim is in progress. */ + | { + tag: "Claiming"; + value?: undefined; +} +/** Some, but not all, of the payment has been observed clearing on chain. */ + | { + tag: "PartiallyCleared"; + value: { + clearedCents: bigint; + }; +} +/** The complete payment has been verified at chain finality. */ + | { + tag: "Cleared"; + value?: undefined; +} +/** An ambiguous effect is retained for reconciliation; inputs remain reserved. */ + | { + tag: "Recovering"; + value?: undefined; +} +/** A definitive failure; the Host has reconciled any possible prior effects. */ + | { + tag: "Failed"; + value: { + reason: HostNativeChatPaymentFailure; + }; +}; +export declare const HostNativeChatPaymentState: S.Codec; +/** Public conversation state; products cannot write this roster back to the Host. */ +export interface HostNativeChatPeer { + /** Recipient wallet identity. */ + identityAccountId: HexString; + /** Username resolved by the Host, if currently available. */ + username?: string; + /** Devices admitted by authenticated native invitation/control messages. */ + devices: Array; + /** Native session topics for subscriptions, not request/response channel hashes. */ + incomingChannels: Array; + /** Whether establishment and legacy-device revocation have been acknowledged. */ + readyForPayments: boolean; +} +export declare const HostNativeChatPeer: S.Codec; +/** Public metadata for one authenticated remote device. */ +export interface HostNativeChatPeerDevice { + /** Remote device's statement signer. */ + accountId: HexString; + /** Remote device's authenticated public X25519 key. */ + chatPublicKey: HexString; +} +export declare const HostNativeChatPeerDevice: S.Codec; +/** Signed ciphertext with the native identity required for durable product delivery. */ +export interface HostNativeChatPrepared { + /** Exact signed ciphertext to submit again when retrying delivery. */ + statement: SignedStatement; + /** Authenticated recipient root identity. */ + peerIdentity: HexString; + /** Native request identity used to correlate delivery acknowledgments. */ + requestId: string; + /** Whether delivery remains pending until a native peer acknowledgment arrives. */ + requiresAck: boolean; + /** Original product intent id for correlating migrated pending UI, when retained. */ + clientRequestId?: string; +} +export declare const HostNativeChatPrepared: S.Codec; +/** Authenticated rich content after private file capabilities have been removed. */ +export interface HostNativeChatRichMessage { + /** Authenticated conversation identity. */ + peerIdentity: HexString; + /** Whether the remote peer authored this content. */ + incoming: boolean; + /** Native request id used for delivery acknowledgment. */ + requestId: string; + /** Native id of this message or edit event. */ + messageId: string; + /** Native timestamp in milliseconds. */ + timestamp: bigint; + /** New message, reply or edit; authorship checks still apply to edits. */ + kind: HostNativeChatRichMessageKind; + /** Ordinary optional text. */ + text?: string; + /** Opaque file handles and safe metadata, never native file references. */ + attachments: Array; +} +export declare const HostNativeChatRichMessage: S.Codec; +/** Native rich-content timeline operation. */ +export type HostNativeChatRichMessageKind = +/** A new ordinary rich message. */ +{ + tag: "Message"; + value?: undefined; +} +/** A new rich message replying to an earlier message. */ + | { + tag: "Reply"; + value: { + messageId: string; + }; +} +/** A replacement of the same author's earlier rich content. */ + | { + tag: "Edited"; + value: { + messageId: string; + }; +}; +export declare const HostNativeChatRichMessageKind: S.Codec; +/** The authenticated native encryption and statement-routing context. */ +export type HostNativeChatRoute = "Invitation" | "Identity" | "Device"; +export declare const HostNativeChatRoute: S.Codec; +/** Continuation metadata for a bounded page of a stable public state snapshot. */ +export interface HostNativeChatStatePage { + /** Opaque identifier of the Host-retained public state snapshot. */ + stateId: HexString; + /** Cursor identifying this page. */ + cursor: number; + /** Cursor to request next; absent when the snapshot is complete. */ + nextCursor?: number; +} +export declare const HostNativeChatStatePage: S.Codec; /** Versioned envelope for [`HostNavigateToError`]. */ export type VersionedHostNavigateToError = /** Version 1 payload. */ @@ -1603,6 +1942,30 @@ export type VersionedHostPocketRemoveCardResponse = value?: undefined; }; export declare const VersionedHostPocketRemoveCardResponse: S.Codec; +/** Versioned envelope for [`HostProductDeviceChatError`]. */ +export type VersionedHostProductDeviceChatError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProductDeviceChatError; +}; +export declare const VersionedHostProductDeviceChatError: S.Codec; +/** Versioned envelope for [`HostProductDeviceChatRequest`]. */ +export type VersionedHostProductDeviceChatRequest = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProductDeviceChatRequest; +}; +export declare const VersionedHostProductDeviceChatRequest: S.Codec; +/** Versioned envelope for [`HostProductDeviceChatResponse`]. */ +export type VersionedHostProductDeviceChatResponse = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProductDeviceChatResponse; +}; +export declare const VersionedHostProductDeviceChatResponse: S.Codec; /** Versioned envelope for [`HostPushNotificationCancelError`]. */ export type VersionedHostPushNotificationCancelError = /** Version 1 payload. */ @@ -4851,6 +5214,239 @@ export interface HostLocaleSubscribeItem { timeZone?: string; } export declare const HostLocaleSubscribeItem: S.Codec; +/** Failure of a Host-owned Chat operation before a public update is available. */ +export type HostProductDeviceChatError = "NotConnected" | "AccessNotGranted" | "UserRejected" | "AllowanceRequired" | "PeerNotReady" | "OperationConflict" | "InvalidRequest" | "InvalidStatement" | "RecipientNotFound" | "InsufficientBalance" | "StorageUnavailable" | "NetworkUnavailable" | "OperationNotFound" | "AttachmentsUnavailable"; +export declare const HostProductDeviceChatError: S.Codec; +/** An operation on the calling product's Host-owned native Chat device. */ +export type V02HostProductDeviceChatRequest = +/** Restore the installation's public device and durable conversation state. */ +{ + tag: "Initialize"; + value?: undefined; +} +/** Resolve a username in the configured network and send a fresh invitation. */ + | { + tag: "Invite"; + value: { + username: string; + text: string; + }; +} +/** Authenticate, decrypt and durably process a native statement. */ + | { + tag: "Receive"; + value: { + statement: SignedStatement; + }; +} +/** Accept an invitation previously authenticated and retained by the Host. */ + | { + tag: "AcceptInvitation"; + value: { + invitationId: HexString; + }; +} +/** Reject an invitation previously authenticated and retained by the Host. */ + | { + tag: "RejectInvitation"; + value: { + invitationId: HexString; + }; +} +/** Send ordinary messages to an established, Host-authenticated peer roster. */ + | { + tag: "Send"; + value: { + peerIdentity: HexString; + requestId: string; + messages: Array; + }; +} +/** Propose one main-purse payment; this operation always requires Host review. */ + | { + tag: "SendPayment"; + value: { + peerIdentity: HexString; + requestId: string; + amountCents: bigint; + }; +} +/** Read a payment's durable status without authorizing another spend. */ + | { + tag: "PaymentStatus"; + value: { + operationId: HexString; + }; +} +/** Resume durable transport work and return newly available public views. */ + | { + tag: "Reconcile"; + value?: undefined; +} +/** Select immutable files in trusted Host UI and send native rich content. */ + | { + tag: "SendAttachments"; + value: { + peerIdentity: HexString; + requestId: string; + text?: string; + }; +} +/** Resume a private download and present or export through trusted Host UI. */ + | { + tag: "OpenAttachment"; + value: { + attachmentId: HexString; + }; +}; +export declare const V02HostProductDeviceChatRequest: S.Codec; +/** Public updates from a Host-owned Chat operation. */ +export interface V02HostProductDeviceChatResponse { + /** Public local device metadata, including its allowance account. */ + device: HostNativeChatDevice; + /** Current authenticated peers and subscription channels. */ + peers: Array; + /** Invitations still awaiting a user decision. */ + invitations: Array; + /** Newly processed safe ordinary messages. */ + messages: Array; + /** Newly processed native delivery acknowledgments. */ + acknowledgments: Array; + /** Current public payment statuses belonging to the calling product. */ + payments: Array; + /** Safe rich-content views and their current private-transfer progress. */ + richMessages: Array; +} +export declare const V02HostProductDeviceChatResponse: 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. */ +{ + tag: "Initialize"; + value?: undefined; +} +/** Independently resolve and bind a peer on the trusted network. */ + | { + tag: "Bind"; + value: { + username: string; + }; +} +/** Validate native plaintext and return signed ciphertext for product delivery. */ + | { + tag: "Prepare"; + value: { + peerIdentity: HexString; + route: HostNativeChatRoute; + plaintext: HexString; + }; +} +/** Authenticate and decrypt a complete external native statement, never own output. */ + | { + tag: "Open"; + value: { + statement: SignedStatement; + }; +} +/** Propose one main-purse payment; this operation requires trusted Host review. */ + | { + tag: "SendPayment"; + value: { + peerIdentity: HexString; + requestId: string; + amountCents: bigint; + }; +} +/** Read durable payment status without authorizing another spend. */ + | { + tag: "PaymentStatus"; + value: { + operationId: HexString; + }; +} +/** Reconcile payment custody and return opaque statements for product delivery. */ + | { + tag: "ReconcilePayments"; + value?: undefined; +} +/** Select files in trusted Host UI and prepare native rich content without delivery. */ + | { + tag: "PrepareAttachments"; + value: { + peerIdentity: HexString; + requestId: string; + text?: string; + }; +} +/** Resume a private download and present or export through trusted Host UI. */ + | { + tag: "OpenAttachment"; + value: { + attachmentId: HexString; + }; +} +/** Acknowledge durable product storage of the legacy view and ordinary ciphertext. */ + | { + tag: "CommitMigration"; + value: { + migrationId: HexString; + }; +} +/** Continue a Host-authenticated incoming batch without supplying new ciphertext. */ + | { + tag: "ContinueOpen"; + value: { + openId: HexString; + cursor: number; + }; +} +/** Continue a bounded snapshot of custody metadata and pending prepared statements. */ + | { + tag: "ContinueState"; + value: { + stateId: HexString; + cursor: number; + }; +} +/** Read configured raw chain units per native Coinage cent, without spending. */ + | { + tag: "PaymentDenomination"; + value?: undefined; +}; +export declare const HostProductDeviceChatRequest: S.Codec; +/** Cryptographic results and custody metadata; products drive delivery and import. */ +export interface HostProductDeviceChatResponse { + /** Public local device metadata, including its allowance account. */ + device: HostNativeChatDevice; + /** Host-authenticated peer and device metadata. */ + peers: Array; + /** Newly resolved peer binding, when requested. */ + binding?: HostNativeChatBinding; + /** Authenticated incoming plaintext; incoming payment import is product-owned. */ + opened: Array; + /** Signed ciphertext for product submission and exact-identity retries. */ + prepared: Array; + /** Durable public payment status, never outgoing bearer secrets. */ + payments: Array; + /** Rich-content metadata and trusted private-transfer progress. */ + richMessages: Array; + /** Legacy public view retained until the product durably commits migration. */ + migration?: V02HostProductDeviceChatResponse; + /** Snapshot identifier to acknowledge only after persisting its view and ciphertext. */ + migrationId?: HexString; + /** Continuation of an authenticated incoming batch, when opening is paginated. */ + openPage?: HostNativeChatOpenPage; + /** Native request identities for invitations in the legacy migration view. */ + migrationInvitations: Array; + /** Continuation of a bounded public state snapshot, when metadata is paginated. */ + statePage?: HostNativeChatStatePage; + /** + * Configured raw chain units per native Coinage cent, only when requested. + * This is positive denomination metadata, never a balance or fiat price. + */ + coinageCentsUnit?: bigint; +} +export declare const HostProductDeviceChatResponse: 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 415687b4a..4dcc8189f 100644 --- a/vendor/truapi/dist/generated/types.js +++ b/vendor/truapi/dist/generated/types.js @@ -1,7 +1,7 @@ // Auto-generated by truapi-codegen. Do not edit. import * as S from '../scale.js'; export const ActionTrigger = S.lazy(() => S.Struct({ messageId: S.str, actionId: S.str, payload: S.Option(S.Hex()) })); -export const AllocatableResource = S.lazy(() => S.TaggedUnion({ StatementStoreAllowance: S._void, BulletinAllowance: S._void, SmartContractAllowance: DerivationIndex, AutoSigning: S._void })); +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 Background = S.lazy(() => S.Struct({ color: ColorToken, shape: S.Option(Shape) })); @@ -164,6 +164,29 @@ export const HostLocaleLocalizedTimestamp = S.lazy(() => S.Struct({ localDate: S export const VersionedHostLocaleSubscribeError = S.lazy(() => S.indexedTaggedUnion({ V2: [1, GenericError] })); export const VersionedHostLocaleSubscribeItem = S.lazy(() => S.indexedTaggedUnion({ V2: [1, HostLocaleSubscribeItem] })); export const VersionedHostLocaleSubscribeRequest = S.lazy(() => S.indexedTaggedUnion({ V2: [1, S._void] })); +export const HostNativeChatAcknowledgment = S.lazy(() => S.Struct({ peerIdentity: S.Hex(32), requestId: S.str, responseCode: S.u8 })); +export const HostNativeChatAttachment = S.lazy(() => S.Struct({ attachmentId: S.Hex(32), metadata: HostNativeChatAttachmentMetadata, state: HostNativeChatAttachmentState })); +export const HostNativeChatAttachmentKind = S.lazy(() => S.TaggedUnion({ File: S._void, Image: S.Struct({ width: S.u32, height: S.u32, thumbnail: S.Option(S.Hex()) }), Video: S.Struct({ durationSeconds: S.u32, thumbnail: S.Option(S.Hex()) }) })); +export const HostNativeChatAttachmentMetadata = S.lazy(() => S.Struct({ mimeType: S.str, sizeBytes: S.u32, kind: HostNativeChatAttachmentKind })); +export const HostNativeChatAttachmentState = S.lazy(() => S.TaggedUnion({ Preparing: S._void, Uploading: S.Struct({ uploadedBytes: S.u32 }), Downloading: S.Struct({ downloadedBytes: S.u32 }), Ready: S._void, Recovering: S._void })); +export const HostNativeChatBinding = S.lazy(() => S.Struct({ peerIdentity: S.Hex(32), peerChatPublicKey: S.Hex(32), identityProof: S.Hex(32) })); +export const HostNativeChatDevice = S.lazy(() => S.Struct({ identityAccountId: S.Hex(32), identityChatPublicKey: S.Hex(32), productAccount: ProductAccountId, accountId: S.Hex(32), chatPublicKey: S.Hex(32) })); +export const HostNativeChatInvitation = S.lazy(() => S.Struct({ invitationId: S.Hex(32), peerIdentity: S.Hex(32), username: S.Option(S.str), timestamp: S.u64, text: S.str })); +export const HostNativeChatMessages = S.lazy(() => S.Struct({ peerIdentity: S.Hex(32), incoming: S.bool, requestId: S.str, messages: S.Vector(S.Hex()) })); +export const HostNativeChatMigrationInvitation = S.lazy(() => S.Struct({ invitationId: S.Hex(32), requestId: S.str })); +export const HostNativeChatOpenPage = S.lazy(() => S.Struct({ openId: S.Hex(32), cursor: S.u32, nextCursor: S.Option(S.u32) })); +export const HostNativeChatOpened = S.lazy(() => S.Struct({ peerIdentity: S.Hex(32), senderAccountId: S.Hex(32), route: HostNativeChatRoute, plaintext: S.Hex() })); +export const HostNativeChatPayment = S.lazy(() => S.Struct({ operationId: S.Hex(32), requestId: S.str, messageId: S.str, timestamp: S.u64, peerIdentity: S.Hex(32), direction: HostNativeChatPaymentDirection, amountCents: S.u64, state: HostNativeChatPaymentState })); +export const HostNativeChatPaymentDirection = S.lazy(() => S.Status("Outgoing", "Incoming")); +export const HostNativeChatPaymentFailure = S.lazy(() => S.Status("Cancelled", "InsufficientBalance", "AlreadySpent", "InvalidMemo", "ChainRejected")); +export const HostNativeChatPaymentState = S.lazy(() => S.TaggedUnion({ Preparing: S._void, Delivering: S._void, Delivered: S._void, Claiming: S._void, PartiallyCleared: S.Struct({ clearedCents: S.u64 }), Cleared: S._void, Recovering: S._void, Failed: S.Struct({ reason: HostNativeChatPaymentFailure }) })); +export const HostNativeChatPeer = S.lazy(() => S.Struct({ identityAccountId: S.Hex(32), username: S.Option(S.str), devices: S.Vector(HostNativeChatPeerDevice), incomingChannels: S.Vector(S.Hex(32)), readyForPayments: S.bool })); +export const HostNativeChatPeerDevice = S.lazy(() => S.Struct({ accountId: S.Hex(32), chatPublicKey: S.Hex(32) })); +export const HostNativeChatPrepared = S.lazy(() => S.Struct({ statement: SignedStatement, peerIdentity: S.Hex(32), requestId: S.str, requiresAck: S.bool, clientRequestId: S.Option(S.str) })); +export const HostNativeChatRichMessage = S.lazy(() => S.Struct({ peerIdentity: S.Hex(32), incoming: S.bool, requestId: S.str, messageId: S.str, timestamp: S.u64, kind: HostNativeChatRichMessageKind, text: S.Option(S.str), attachments: S.Vector(HostNativeChatAttachment) })); +export const HostNativeChatRichMessageKind = S.lazy(() => S.TaggedUnion({ Message: S._void, Reply: S.Struct({ messageId: S.str }), Edited: S.Struct({ messageId: S.str }) })); +export const HostNativeChatRoute = S.lazy(() => S.Status("Invitation", "Identity", "Device")); +export const HostNativeChatStatePage = S.lazy(() => S.Struct({ stateId: S.Hex(32), cursor: S.u32, nextCursor: S.Option(S.u32) })); export const VersionedHostNavigateToError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostNavigateToError] })); export const VersionedHostNavigateToRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostNavigateToRequest] })); export const VersionedHostNavigateToResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); @@ -186,6 +209,9 @@ export const VersionedHostPocketListSubscribeRequest = S.lazy(() => S.indexedTag export const VersionedHostPocketRemoveCardError = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostPocketRemoveCardError] })); export const VersionedHostPocketRemoveCardRequest = S.lazy(() => S.indexedTaggedUnion({ V1: [0, HostPocketRemoveCardRequest] })); export const VersionedHostPocketRemoveCardResponse = S.lazy(() => S.indexedTaggedUnion({ V1: [0, S._void] })); +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 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] })); @@ -476,6 +502,11 @@ export const HostLocalStorageReadRequest = S.lazy(() => S.Struct({ product: S.Op export const HostLocaleLocalizeTimestampsRequest = S.lazy(() => S.Struct({ timestampsMs: S.Vector(S.u64), languageTag: S.str, timeZone: S.str })); export const HostLocaleLocalizeTimestampsResponse = S.lazy(() => S.Struct({ timestamps: S.Vector(HostLocaleLocalizedTimestamp) })); export const HostLocaleSubscribeItem = S.lazy(() => S.Struct({ languageTag: S.str, timeZone: S.Option(S.str) })); +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 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 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 432b2d39d..7318c27af 100644 --- a/vendor/truapi/dist/generated/wire-decode.js +++ b/vendor/truapi/dist/generated/wire-decode.js @@ -72,6 +72,10 @@ export const WIRE_DECODE_TABLE = { 0: (payload) => T.VersionedHostAccountRingVrfSignRequest.dec(payload), 1: (payload) => S.Result(T.VersionedHostAccountRingVrfSignResponse, S.CallError(T.VersionedHostAccountRingVrfSignError)).dec(payload), }, + [W.ACCOUNT_PRODUCT_DEVICE_CHAT.trait * 256 + W.ACCOUNT_PRODUCT_DEVICE_CHAT.method]: { + 0: (payload) => T.VersionedHostProductDeviceChatRequest.dec(payload), + 1: (payload) => S.Result(T.VersionedHostProductDeviceChatResponse, S.CallError(T.VersionedHostProductDeviceChatError)).dec(payload), + }, [W.CHAIN_FOLLOW_HEAD_SUBSCRIBE.trait * 256 + W.CHAIN_FOLLOW_HEAD_SUBSCRIBE.method]: { 0: (payload) => T.VersionedRemoteChainHeadFollowRequest.dec(payload), 1: (payload) => T.VersionedRemoteChainHeadFollowItem.dec(payload), diff --git a/vendor/truapi/dist/generated/wire-table.d.ts b/vendor/truapi/dist/generated/wire-table.d.ts index a01ea29cd..f3bb2ba4c 100644 --- a/vendor/truapi/dist/generated/wire-table.d.ts +++ b/vendor/truapi/dist/generated/wire-table.d.ts @@ -78,6 +78,11 @@ export declare const ACCOUNT_RING_VRF_SIGN: { readonly method: 10; readonly kind: "request"; }; +export declare const ACCOUNT_PRODUCT_DEVICE_CHAT: { + readonly trait: 2; + readonly method: 12; + readonly kind: "request"; +}; export declare const CHAIN_FOLLOW_HEAD_SUBSCRIBE: { readonly trait: 3; readonly method: 0; diff --git a/vendor/truapi/dist/generated/wire-table.js b/vendor/truapi/dist/generated/wire-table.js index dd003d38d..129a15347 100644 --- a/vendor/truapi/dist/generated/wire-table.js +++ b/vendor/truapi/dist/generated/wire-table.js @@ -89,6 +89,11 @@ export const ACCOUNT_RING_VRF_SIGN = { method: 10, kind: "request", }; +export const ACCOUNT_PRODUCT_DEVICE_CHAT = { + trait: 2, + method: 12, + kind: "request", +}; export const CHAIN_FOLLOW_HEAD_SUBSCRIBE = { trait: 3, method: 0, diff --git a/vendor/truapi/dist/playground/codegen/services.js b/vendor/truapi/dist/playground/codegen/services.js index b32aac859..b226b7b29 100644 --- a/vendor/truapi/dist/playground/codegen/services.js +++ b/vendor/truapi/dist/playground/codegen/services.js @@ -114,6 +114,17 @@ export const services = [ exampleSource: 'const productContext = await truapi.system.getProductContext();\nassert(productContext.isOk(), "getProductContext failed:", productContext);\n\nconst result = await truapi.account.ringVrfSign({\n keyHandle: {\n dotNsIdentifier: productContext.value.productId,\n derivationIndex: { tag: "Index", value: 0 },\n },\n message: "0x48656c6c6f",\n});\nassert(result.isOk(), "ringVrfSign failed:", result);\nconsole.log("ring VRF signature:", result.value);', requestType: "host-account-ring-vrf-sign-request", }, + { + name: "product_device_chat", + type: "unary", + signature: "deviceChat(request: HostProductDeviceChatRequest): Promise>>", + docUrl: "api/account/trait.Account.html#method.product_device_chat", + description: "Use a non-exportable Host Chat device for native cryptographic operations\nand reviewed main-purse payments. The product owns native lifecycle frames,\nsubscriptions, delivery, retries, history, and acknowledgments.\n\n`Bind` resolves the peer independently. `Prepare` validates native plaintext\nand returns signed ciphertext for product submission. `Open` authenticates\ncomplete external statements and rejects reflected local output; it is not\nan arbitrary decryption primitive. Incoming plaintext can contain incoming\nbearer coin keys: persist the import intent securely and use generic payment\ntop-up before acknowledging. Wallet/device keys and outgoing main-purse\ncoin secrets never leave the Host.\n\n`Initialize` also advances private file transfers. Persist any legacy\nmigration 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;\npersist every page before committing its migration.\n\nMethod 11 (the former raw-crypto interface) and method 12's former V1 actor\noperations are retired, not forwarded. This boundary uses V2 payloads.", + requestDescription: "HostProductDeviceChatRequest", + exampleSource: 'const result = await truapi.account.deviceChat({ tag: "Initialize" });\nassert(result.isOk(), "deviceChat failed:", result);\nconsole.log("Host-owned Chat device:", result.value.device);', + requestType: "host-product-device-chat-request", + responseType: "host-product-device-chat-response", + }, ], }, { diff --git a/vendor/truapi/dist/playground/codegen/truapi-dts.d.ts b/vendor/truapi/dist/playground/codegen/truapi-dts.d.ts index d6feac49f..01b7c7553 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};\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/** 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 [`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/** 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 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 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 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: \"7c073d1a8c5db314\";\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 * 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/** 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"; diff --git a/vendor/truapi/dist/playground/codegen/truapi-dts.js b/vendor/truapi/dist/playground/codegen/truapi-dts.js index 36ec0e588..0820cb436 100644 --- a/vendor/truapi/dist/playground/codegen/truapi-dts.js +++ b/vendor/truapi/dist/playground/codegen/truapi-dts.js @@ -584,6 +584,14 @@ export type AllocatableResource = | { tag: "AutoSigning"; value?: undefined; +} +/** + * Current UTC-day Statement Store allowance whose target is the product + * account selected by this derivation index. + */ + | { + tag: "ProductStatementStoreAllowance"; + value: DerivationIndex; }; export const AllocatableResource: Codec; /** Outcome of allocating a single resource (RFC 0010). */ @@ -1968,6 +1976,337 @@ export type VersionedHostLocaleSubscribeRequest = value?: undefined; }; export const VersionedHostLocaleSubscribeRequest: Codec; +/** A peer's native delivery acknowledgment, not a payment-clearing receipt. */ +export interface HostNativeChatAcknowledgment { + /** Authenticated acknowledging identity. */ + peerIdentity: HexString; + /** Acknowledged native request identifier. */ + requestId: string; + /** Native response code; zero denotes successful delivery processing. */ + responseCode: number; +} +export const HostNativeChatAcknowledgment: Codec; +/** Public attachment handle; only the Host can resolve its private backing. */ +export interface HostNativeChatAttachment { + /** Opaque handle scoped to the current wallet, network and calling product. */ + attachmentId: HexString; + /** Non-secret native metadata. */ + metadata: HostNativeChatAttachmentMetadata; + /** Current durable transfer progress. */ + state: HostNativeChatAttachmentState; +} +export const HostNativeChatAttachment: Codec; +/** Public native media metadata; thumbnails are BlurHash text, not executable images. */ +export type HostNativeChatAttachmentKind = +/** A general document or other opaque file. */ +{ + tag: "File"; + value?: undefined; +} +/** An image with native dimensions and an optional UTF-8 BlurHash. */ + | { + tag: "Image"; + value: { + width: number; + height: number; + thumbnail?: HexString; + }; +} +/** A video with native duration and an optional UTF-8 BlurHash. */ + | { + tag: "Video"; + value: { + durationSeconds: number; + thumbnail?: HexString; + }; +}; +export const HostNativeChatAttachmentKind: Codec; +/** Safe attachment description, independent of private transfer credentials. */ +export interface HostNativeChatAttachmentMetadata { + /** Validated media type; it does not authorize execution or network loading. */ + mimeType: string; + /** Exact native file size, verified against the downloaded root and chunks. */ + sizeBytes: number; + /** General file, image or video metadata. */ + kind: HostNativeChatAttachmentKind; +} +export const HostNativeChatAttachmentMetadata: Codec; +/** Durable transfer progress, distinct from message delivery acknowledgment. */ +export type HostNativeChatAttachmentState = +/** The Host is securing an immutable selected source. */ +{ + tag: "Preparing"; + value?: undefined; +} +/** Native HOP entries are being uploaded. */ + | { + tag: "Uploading"; + value: { + uploadedBytes: number; + }; +} +/** Verified file bytes are being committed to private local storage. */ + | { + tag: "Downloading"; + value: { + downloadedBytes: number; + }; +} +/** Complete verified bytes are available through trusted Host presentation. */ + | { + tag: "Ready"; + value?: undefined; +} +/** An interrupted transfer retains its exact credentials and progress for retry. */ + | { + tag: "Recovering"; + value?: undefined; +}; +export const HostNativeChatAttachmentState: Codec; +/** Peer cryptographic identity independently resolved and bound by the Host. */ +export interface HostNativeChatBinding { + /** Authenticated peer root identity. */ + peerIdentity: HexString; + /** Peer identity-level native Chat encryption key. */ + peerChatPublicKey: HexString; + /** Identity proof used in the native invitation handshake. */ + identityProof: HexString; +} +export const HostNativeChatBinding: Codec; +/** The Host-owned device's public identity and statement-signing account. */ +export interface HostNativeChatDevice { + /** Wallet identity on the configured People chain. */ + identityAccountId: HexString; + /** Wallet identity's public X25519 key. */ + identityChatPublicKey: HexString; + /** Product account used to obtain a statement-store allowance for this device. */ + productAccount: ProductAccountId; + /** Public statement signer for the Host-owned device. */ + accountId: HexString; + /** Public X25519 key; its secret never leaves the Host. */ + chatPublicKey: HexString; +} +export const HostNativeChatDevice: Codec; +/** An authenticated invitation awaiting the user's Chat decision. */ +export interface HostNativeChatInvitation { + /** Host-generated stable invitation identifier. */ + invitationId: HexString; + /** Authenticated sender identity. */ + peerIdentity: HexString; + /** Host-resolved sender username, when available. */ + username?: string; + /** Authenticated native invitation timestamp in milliseconds. */ + timestamp: bigint; + /** Ordinary initial text, never an embedded payment or control message. */ + text: string; +} +export const HostNativeChatInvitation: Codec; +/** Safe ordinary messages from one authenticated native request. */ +export interface HostNativeChatMessages { + /** Authenticated counterparty identity. */ + peerIdentity: HexString; + /** Whether the peer sent these messages; false also covers our welcome text. */ + incoming: boolean; + /** Native request identifier, retained for message-delivery correlation. */ + requestId: string; + /** Native message encodings after custody-sensitive content is removed. */ + messages: Array; +} +export const HostNativeChatMessages: Codec; +/** Native request identity needed to answer a migrated legacy invitation. */ +export interface HostNativeChatMigrationInvitation { + /** Invitation handle in the accompanying legacy public view. */ + invitationId: HexString; + /** Original native request identity to acknowledge when answering. */ + requestId: string; +} +export const HostNativeChatMigrationInvitation: Codec; +/** Continuation metadata for a bounded page of authenticated incoming plaintext. */ +export interface HostNativeChatOpenPage { + /** Opaque identifier of the authenticated opening operation. */ + openId: HexString; + /** Cursor identifying this page. */ + cursor: number; + /** Cursor to request next; absent when the authenticated batch is complete. */ + nextCursor?: number; +} +export const HostNativeChatOpenPage: Codec; +/** Authenticated incoming native plaintext, potentially containing incoming coin keys. */ +export interface HostNativeChatOpened { + /** Authenticated peer root identity, never the local wallet's own identity. */ + peerIdentity: HexString; + /** Account that signed the accepted native statement. */ + senderAccountId: HexString; + /** Authenticated native context of the incoming statement. */ + route: HostNativeChatRoute; + /** Native invitation or tagged request/response plaintext; never outgoing payment memos. */ + plaintext: HexString; +} +export const HostNativeChatOpened: Codec; +/** A product-visible payment card; it contains no spendable memo material. */ +export interface HostNativeChatPayment { + /** Durable, product-scoped operation identifier. */ + operationId: HexString; + /** Caller request id for outgoing payments; native request id for incoming ones. */ + requestId: string; + /** Native message id used to place the payment in conversation history. */ + messageId: string; + /** Native message timestamp in milliseconds. */ + timestamp: bigint; + /** Counterparty identity authenticated by the Host. */ + peerIdentity: HexString; + /** Incoming or outgoing relative to the current wallet. */ + direction: HostNativeChatPaymentDirection; + /** Exact requested/received value in cents. */ + amountCents: bigint; + /** Durable transport/clearing state. */ + state: HostNativeChatPaymentState; +} +export const HostNativeChatPayment: Codec; +/** Payment direction relative to the current wallet. */ +export type HostNativeChatPaymentDirection = "Outgoing" | "Incoming"; +export const HostNativeChatPaymentDirection: Codec; +/** Public, non-secret payment failure categories. */ +export type HostNativeChatPaymentFailure = "Cancelled" | "InsufficientBalance" | "AlreadySpent" | "InvalidMemo" | "ChainRejected"; +export const HostNativeChatPaymentFailure: Codec; +/** Durable payment state. Delivery and on-chain clearing are deliberately distinct. */ +export type HostNativeChatPaymentState = +/** Approved inputs are reserved; required split/unload work is in progress. */ +{ + tag: "Preparing"; + value?: undefined; +} +/** The encrypted memo is durable and transport delivery is being retried. */ + | { + tag: "Delivering"; + value?: undefined; +} +/** The peer acknowledged the memo; settlement has not yet been established. */ + | { + tag: "Delivered"; + value?: undefined; +} +/** Received secrets are durably held while their claim is in progress. */ + | { + tag: "Claiming"; + value?: undefined; +} +/** Some, but not all, of the payment has been observed clearing on chain. */ + | { + tag: "PartiallyCleared"; + value: { + clearedCents: bigint; + }; +} +/** The complete payment has been verified at chain finality. */ + | { + tag: "Cleared"; + value?: undefined; +} +/** An ambiguous effect is retained for reconciliation; inputs remain reserved. */ + | { + tag: "Recovering"; + value?: undefined; +} +/** A definitive failure; the Host has reconciled any possible prior effects. */ + | { + tag: "Failed"; + value: { + reason: HostNativeChatPaymentFailure; + }; +}; +export const HostNativeChatPaymentState: Codec; +/** Public conversation state; products cannot write this roster back to the Host. */ +export interface HostNativeChatPeer { + /** Recipient wallet identity. */ + identityAccountId: HexString; + /** Username resolved by the Host, if currently available. */ + username?: string; + /** Devices admitted by authenticated native invitation/control messages. */ + devices: Array; + /** Native session topics for subscriptions, not request/response channel hashes. */ + incomingChannels: Array; + /** Whether establishment and legacy-device revocation have been acknowledged. */ + readyForPayments: boolean; +} +export const HostNativeChatPeer: Codec; +/** Public metadata for one authenticated remote device. */ +export interface HostNativeChatPeerDevice { + /** Remote device's statement signer. */ + accountId: HexString; + /** Remote device's authenticated public X25519 key. */ + chatPublicKey: HexString; +} +export const HostNativeChatPeerDevice: Codec; +/** Signed ciphertext with the native identity required for durable product delivery. */ +export interface HostNativeChatPrepared { + /** Exact signed ciphertext to submit again when retrying delivery. */ + statement: SignedStatement; + /** Authenticated recipient root identity. */ + peerIdentity: HexString; + /** Native request identity used to correlate delivery acknowledgments. */ + requestId: string; + /** Whether delivery remains pending until a native peer acknowledgment arrives. */ + requiresAck: boolean; + /** Original product intent id for correlating migrated pending UI, when retained. */ + clientRequestId?: string; +} +export const HostNativeChatPrepared: Codec; +/** Authenticated rich content after private file capabilities have been removed. */ +export interface HostNativeChatRichMessage { + /** Authenticated conversation identity. */ + peerIdentity: HexString; + /** Whether the remote peer authored this content. */ + incoming: boolean; + /** Native request id used for delivery acknowledgment. */ + requestId: string; + /** Native id of this message or edit event. */ + messageId: string; + /** Native timestamp in milliseconds. */ + timestamp: bigint; + /** New message, reply or edit; authorship checks still apply to edits. */ + kind: HostNativeChatRichMessageKind; + /** Ordinary optional text. */ + text?: string; + /** Opaque file handles and safe metadata, never native file references. */ + attachments: Array; +} +export const HostNativeChatRichMessage: Codec; +/** Native rich-content timeline operation. */ +export type HostNativeChatRichMessageKind = +/** A new ordinary rich message. */ +{ + tag: "Message"; + value?: undefined; +} +/** A new rich message replying to an earlier message. */ + | { + tag: "Reply"; + value: { + messageId: string; + }; +} +/** A replacement of the same author's earlier rich content. */ + | { + tag: "Edited"; + value: { + messageId: string; + }; +}; +export const HostNativeChatRichMessageKind: Codec; +/** The authenticated native encryption and statement-routing context. */ +export type HostNativeChatRoute = "Invitation" | "Identity" | "Device"; +export const HostNativeChatRoute: Codec; +/** Continuation metadata for a bounded page of a stable public state snapshot. */ +export interface HostNativeChatStatePage { + /** Opaque identifier of the Host-retained public state snapshot. */ + stateId: HexString; + /** Cursor identifying this page. */ + cursor: number; + /** Cursor to request next; absent when the snapshot is complete. */ + nextCursor?: number; +} +export const HostNativeChatStatePage: Codec; /** Versioned envelope for [\`HostNavigateToError\`]. */ export type VersionedHostNavigateToError = /** Version 1 payload. */ @@ -2139,6 +2478,30 @@ export type VersionedHostPocketRemoveCardResponse = value?: undefined; }; export const VersionedHostPocketRemoveCardResponse: Codec; +/** Versioned envelope for [\`HostProductDeviceChatError\`]. */ +export type VersionedHostProductDeviceChatError = +/** Version 1 payload. */ +{ + tag: "V1"; + value: HostProductDeviceChatError; +}; +export const VersionedHostProductDeviceChatError: Codec; +/** Versioned envelope for [\`HostProductDeviceChatRequest\`]. */ +export type VersionedHostProductDeviceChatRequest = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProductDeviceChatRequest; +}; +export const VersionedHostProductDeviceChatRequest: Codec; +/** Versioned envelope for [\`HostProductDeviceChatResponse\`]. */ +export type VersionedHostProductDeviceChatResponse = +/** Version 2 payload. */ +{ + tag: "V2"; + value: HostProductDeviceChatResponse; +}; +export const VersionedHostProductDeviceChatResponse: Codec; /** Versioned envelope for [\`HostPushNotificationCancelError\`]. */ export type VersionedHostPushNotificationCancelError = /** Version 1 payload. */ @@ -5387,6 +5750,239 @@ export interface HostLocaleSubscribeItem { timeZone?: string; } export const HostLocaleSubscribeItem: Codec; +/** Failure of a Host-owned Chat operation before a public update is available. */ +export type HostProductDeviceChatError = "NotConnected" | "AccessNotGranted" | "UserRejected" | "AllowanceRequired" | "PeerNotReady" | "OperationConflict" | "InvalidRequest" | "InvalidStatement" | "RecipientNotFound" | "InsufficientBalance" | "StorageUnavailable" | "NetworkUnavailable" | "OperationNotFound" | "AttachmentsUnavailable"; +export const HostProductDeviceChatError: Codec; +/** An operation on the calling product's Host-owned native Chat device. */ +export type V02HostProductDeviceChatRequest = +/** Restore the installation's public device and durable conversation state. */ +{ + tag: "Initialize"; + value?: undefined; +} +/** Resolve a username in the configured network and send a fresh invitation. */ + | { + tag: "Invite"; + value: { + username: string; + text: string; + }; +} +/** Authenticate, decrypt and durably process a native statement. */ + | { + tag: "Receive"; + value: { + statement: SignedStatement; + }; +} +/** Accept an invitation previously authenticated and retained by the Host. */ + | { + tag: "AcceptInvitation"; + value: { + invitationId: HexString; + }; +} +/** Reject an invitation previously authenticated and retained by the Host. */ + | { + tag: "RejectInvitation"; + value: { + invitationId: HexString; + }; +} +/** Send ordinary messages to an established, Host-authenticated peer roster. */ + | { + tag: "Send"; + value: { + peerIdentity: HexString; + requestId: string; + messages: Array; + }; +} +/** Propose one main-purse payment; this operation always requires Host review. */ + | { + tag: "SendPayment"; + value: { + peerIdentity: HexString; + requestId: string; + amountCents: bigint; + }; +} +/** Read a payment's durable status without authorizing another spend. */ + | { + tag: "PaymentStatus"; + value: { + operationId: HexString; + }; +} +/** Resume durable transport work and return newly available public views. */ + | { + tag: "Reconcile"; + value?: undefined; +} +/** Select immutable files in trusted Host UI and send native rich content. */ + | { + tag: "SendAttachments"; + value: { + peerIdentity: HexString; + requestId: string; + text?: string; + }; +} +/** Resume a private download and present or export through trusted Host UI. */ + | { + tag: "OpenAttachment"; + value: { + attachmentId: HexString; + }; +}; +export const V02HostProductDeviceChatRequest: Codec; +/** Public updates from a Host-owned Chat operation. */ +export interface V02HostProductDeviceChatResponse { + /** Public local device metadata, including its allowance account. */ + device: HostNativeChatDevice; + /** Current authenticated peers and subscription channels. */ + peers: Array; + /** Invitations still awaiting a user decision. */ + invitations: Array; + /** Newly processed safe ordinary messages. */ + messages: Array; + /** Newly processed native delivery acknowledgments. */ + acknowledgments: Array; + /** Current public payment statuses belonging to the calling product. */ + payments: Array; + /** Safe rich-content views and their current private-transfer progress. */ + richMessages: Array; +} +export const V02HostProductDeviceChatResponse: 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. */ +{ + tag: "Initialize"; + value?: undefined; +} +/** Independently resolve and bind a peer on the trusted network. */ + | { + tag: "Bind"; + value: { + username: string; + }; +} +/** Validate native plaintext and return signed ciphertext for product delivery. */ + | { + tag: "Prepare"; + value: { + peerIdentity: HexString; + route: HostNativeChatRoute; + plaintext: HexString; + }; +} +/** Authenticate and decrypt a complete external native statement, never own output. */ + | { + tag: "Open"; + value: { + statement: SignedStatement; + }; +} +/** Propose one main-purse payment; this operation requires trusted Host review. */ + | { + tag: "SendPayment"; + value: { + peerIdentity: HexString; + requestId: string; + amountCents: bigint; + }; +} +/** Read durable payment status without authorizing another spend. */ + | { + tag: "PaymentStatus"; + value: { + operationId: HexString; + }; +} +/** Reconcile payment custody and return opaque statements for product delivery. */ + | { + tag: "ReconcilePayments"; + value?: undefined; +} +/** Select files in trusted Host UI and prepare native rich content without delivery. */ + | { + tag: "PrepareAttachments"; + value: { + peerIdentity: HexString; + requestId: string; + text?: string; + }; +} +/** Resume a private download and present or export through trusted Host UI. */ + | { + tag: "OpenAttachment"; + value: { + attachmentId: HexString; + }; +} +/** Acknowledge durable product storage of the legacy view and ordinary ciphertext. */ + | { + tag: "CommitMigration"; + value: { + migrationId: HexString; + }; +} +/** Continue a Host-authenticated incoming batch without supplying new ciphertext. */ + | { + tag: "ContinueOpen"; + value: { + openId: HexString; + cursor: number; + }; +} +/** Continue a bounded snapshot of custody metadata and pending prepared statements. */ + | { + tag: "ContinueState"; + value: { + stateId: HexString; + cursor: number; + }; +} +/** Read configured raw chain units per native Coinage cent, without spending. */ + | { + tag: "PaymentDenomination"; + value?: undefined; +}; +export const HostProductDeviceChatRequest: Codec; +/** Cryptographic results and custody metadata; products drive delivery and import. */ +export interface HostProductDeviceChatResponse { + /** Public local device metadata, including its allowance account. */ + device: HostNativeChatDevice; + /** Host-authenticated peer and device metadata. */ + peers: Array; + /** Newly resolved peer binding, when requested. */ + binding?: HostNativeChatBinding; + /** Authenticated incoming plaintext; incoming payment import is product-owned. */ + opened: Array; + /** Signed ciphertext for product submission and exact-identity retries. */ + prepared: Array; + /** Durable public payment status, never outgoing bearer secrets. */ + payments: Array; + /** Rich-content metadata and trusted private-transfer progress. */ + richMessages: Array; + /** Legacy public view retained until the product durably commits migration. */ + migration?: V02HostProductDeviceChatResponse; + /** Snapshot identifier to acknowledge only after persisting its view and ciphertext. */ + migrationId?: HexString; + /** Continuation of an authenticated incoming batch, when opening is paginated. */ + openPage?: HostNativeChatOpenPage; + /** Native request identities for invitations in the legacy migration view. */ + migrationInvitations: Array; + /** Continuation of a bounded public state snapshot, when metadata is paginated. */ + statePage?: HostNativeChatStatePage; + /** + * Configured raw chain units per native Coinage cent, only when requested. + * This is positive denomination metadata, never a balance or fiat price. + */ + coinageCentsUnit?: bigint; +} +export const HostProductDeviceChatResponse: Codec; /** Cross-axis alignment of \`Row\` children. */ export type VerticalAlignment = "Top" | "Center" | "Bottom"; export const VerticalAlignment: Codec; @@ -5576,6 +6172,29 @@ export import HostLocaleLocalizedTimestamp = T.HostLocaleLocalizedTimestamp; export import VersionedHostLocaleSubscribeError = T.VersionedHostLocaleSubscribeError; export import VersionedHostLocaleSubscribeItem = T.VersionedHostLocaleSubscribeItem; export import VersionedHostLocaleSubscribeRequest = T.VersionedHostLocaleSubscribeRequest; +export import HostNativeChatAcknowledgment = T.HostNativeChatAcknowledgment; +export import HostNativeChatAttachment = T.HostNativeChatAttachment; +export import HostNativeChatAttachmentKind = T.HostNativeChatAttachmentKind; +export import HostNativeChatAttachmentMetadata = T.HostNativeChatAttachmentMetadata; +export import HostNativeChatAttachmentState = T.HostNativeChatAttachmentState; +export import HostNativeChatBinding = T.HostNativeChatBinding; +export import HostNativeChatDevice = T.HostNativeChatDevice; +export import HostNativeChatInvitation = T.HostNativeChatInvitation; +export import HostNativeChatMessages = T.HostNativeChatMessages; +export import HostNativeChatMigrationInvitation = T.HostNativeChatMigrationInvitation; +export import HostNativeChatOpenPage = T.HostNativeChatOpenPage; +export import HostNativeChatOpened = T.HostNativeChatOpened; +export import HostNativeChatPayment = T.HostNativeChatPayment; +export import HostNativeChatPaymentDirection = T.HostNativeChatPaymentDirection; +export import HostNativeChatPaymentFailure = T.HostNativeChatPaymentFailure; +export import HostNativeChatPaymentState = T.HostNativeChatPaymentState; +export import HostNativeChatPeer = T.HostNativeChatPeer; +export import HostNativeChatPeerDevice = T.HostNativeChatPeerDevice; +export import HostNativeChatPrepared = T.HostNativeChatPrepared; +export import HostNativeChatRichMessage = T.HostNativeChatRichMessage; +export import HostNativeChatRichMessageKind = T.HostNativeChatRichMessageKind; +export import HostNativeChatRoute = T.HostNativeChatRoute; +export import HostNativeChatStatePage = T.HostNativeChatStatePage; export import VersionedHostNavigateToError = T.VersionedHostNavigateToError; export import VersionedHostNavigateToRequest = T.VersionedHostNavigateToRequest; export import VersionedHostNavigateToResponse = T.VersionedHostNavigateToResponse; @@ -5598,6 +6217,9 @@ export import VersionedHostPocketListSubscribeRequest = T.VersionedHostPocketLis export import VersionedHostPocketRemoveCardError = T.VersionedHostPocketRemoveCardError; export import VersionedHostPocketRemoveCardRequest = T.VersionedHostPocketRemoveCardRequest; export import VersionedHostPocketRemoveCardResponse = T.VersionedHostPocketRemoveCardResponse; +export import VersionedHostProductDeviceChatError = T.VersionedHostProductDeviceChatError; +export import VersionedHostProductDeviceChatRequest = T.VersionedHostProductDeviceChatRequest; +export import VersionedHostProductDeviceChatResponse = T.VersionedHostProductDeviceChatResponse; export import VersionedHostPushNotificationCancelError = T.VersionedHostPushNotificationCancelError; export import VersionedHostPushNotificationCancelRequest = T.VersionedHostPushNotificationCancelRequest; export import VersionedHostPushNotificationCancelResponse = T.VersionedHostPushNotificationCancelResponse; @@ -5888,6 +6510,11 @@ export import HostLocalStorageReadRequest = T.HostLocalStorageReadRequest; export import HostLocaleLocalizeTimestampsRequest = T.HostLocaleLocalizeTimestampsRequest; export import HostLocaleLocalizeTimestampsResponse = T.HostLocaleLocalizeTimestampsResponse; export import HostLocaleSubscribeItem = T.HostLocaleSubscribeItem; +export import HostProductDeviceChatError = T.HostProductDeviceChatError; +export import V02HostProductDeviceChatRequest = T.V02HostProductDeviceChatRequest; +export import V02HostProductDeviceChatResponse = T.V02HostProductDeviceChatResponse; +export import HostProductDeviceChatRequest = T.HostProductDeviceChatRequest; +export import HostProductDeviceChatResponse = T.HostProductDeviceChatResponse; export import VerticalAlignment = T.VerticalAlignment; export import VrfSignature = T.VrfSignature; export import VrfTranscriptItem = T.VrfTranscriptItem; @@ -6345,7 +6972,7 @@ export { ResultAsync, SubscriptionError }; export type { CallOptions, HostInitiatedSubscriptionHandler, ObservableLike, Observer, Result, Subscription, TrUApiTransport }; export declare const TRUAPI_VERSION: 2; export declare const TRUAPI_CODEC_VERSION: 3; -export declare const TRUAPI_WIRE_SCHEMA_HASH: "7c073d1a8c5db314"; +export declare const TRUAPI_WIRE_SCHEMA_HASH: "f7be28c22289b365"; /** Account lookup, aliasing, and proof generation. */ export declare class AccountClient { #private; @@ -6373,6 +7000,29 @@ export declare class AccountClient { listRingVrfKeys(request: T.HostAccountListRingVrfKeysRequest, options?: CallOptions): ResultAsync, S.CallErrorValue>; /** Sign bytes directly with a registered ring-VRF member key. */ ringVrfSign(request: T.HostAccountRingVrfSignRequest, options?: CallOptions): ResultAsync>; + /** + * Use a non-exportable Host Chat device for native cryptographic operations + * and reviewed main-purse payments. The product owns native lifecycle frames, + * subscriptions, delivery, retries, history, and acknowledgments. + * + * \`Bind\` resolves the peer independently. \`Prepare\` validates native plaintext + * and returns signed ciphertext for product submission. \`Open\` authenticates + * complete external statements and rejects reflected local output; it is not + * an arbitrary decryption primitive. Incoming plaintext can contain incoming + * bearer coin keys: persist the import intent securely and use generic payment + * top-up before acknowledging. Wallet/device keys and outgoing main-purse + * coin secrets never leave the Host. + * + * \`Initialize\` also advances private file transfers. Persist any legacy + * migration view and ordinary prepared statements before \`CommitMigration\`. + * \`ContinueOpen\` retrieves the next bounded page of an authenticated batch. + * \`ContinueState\` retrieves remaining pages of a stable public state snapshot; + * persist every page before committing its migration. + * + * Method 11 (the former raw-crypto interface) and method 12's former V1 actor + * operations are retired, not forwarded. This boundary uses V2 payloads. + */ + deviceChat(request: T.HostProductDeviceChatRequest, options?: CallOptions): ResultAsync>; /** * List non-product accounts the user owns. *