diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40d607ad2..9cafab581 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,6 +139,12 @@ jobs: - name: Run codegen run: ./scripts/codegen.sh + - name: Check generated Rust output is committed + run: | + git diff --exit-code -- \ + rust/crates/truapi-client/src/generated.rs \ + rust/crates/truapi-server/src/generated \ + rust/crates/truapi-server/src/wasm/generated_bridge.rs - name: Check Rust/TS wire table parity run: TRUAPI_REQUIRE_GENERATED_TS=1 cargo test -p truapi-server --test wire_table_ts_parity diff --git a/CHANGELOG.md b/CHANGELOG.md index 39d9b081e..664fd8773 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,27 @@ All notable changes to the TrUAPI protocol are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), generated from [Conventional Commits](https://www.conventionalcommits.org/). +## [Unreleased] + +### Changed + +- isolate the optional PolkaVM runtime in `truapi-polkavm-host`; keep the base + server and browser asset distribution independent, and pin cooperative update + deadlines, multi-touch input, and image clipboard output (#540) + +### Added + +- Generate a transport-neutral `no_std` Rust client with typed request, + subscription, result-subscription, and host-initiated Worker subscription + codecs. +- Generate complete App, Widget, Worker, and Worker-only method catalogs from + the canonical protocol schema. + +### Fixed + +- return a decode error instead of trapping when subscription helpers receive a + request descriptor + ## [0.13.1] - 2026-09-02 ### Fixed diff --git a/CLAUDE.md b/CLAUDE.md index b1e193510..52fd45b41 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,6 +14,8 @@ rust/crates/ truapi-platform/ Host syscall traits (storage, navigation, consent, ...) truapi-provider/ network provider backends (WebSocket RPC or smoldot light-client) truapi-server/ Rust runtime hosts implement; ships as WASM (browser/node) + truapi-polkavm-host/ optional native composition pinned to + paritytech/polkavm-host-runtime js/packages/ truapi/ @parity/truapi TS package; generated TS lives under ignored paths truapi-host/ @parity/truapi-host: WASM-backed host runtime. Subpath entries: @@ -57,6 +59,13 @@ scripts/truapi-host-installer.sh .github/consumers.json maps each released package to the repos notified by a bump issue ``` +The PolkaVM runtime implementation, wire crates, browser package, and ABI +contract live in `paritytech/polkavm-host-runtime`. The base `truapi-server` +must remain PolkaVM-free. Native integrations use the optional +`truapi-polkavm-host` composition crate; browser integrations consume +`@parity/polkavm-browser-runtime` directly. Never copy or export browser assets +from this repository. + ### Crate + binding invariants - `truapi` is canonical; runtime crates re-export rather than redefine. New diff --git a/Cargo.lock b/Cargo.lock index e79f1af41..e9230b9a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,15 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "1.0.0" @@ -126,7 +135,7 @@ dependencies = [ "objc2-foundation", "parking_lot", "percent-encoding", - "windows-sys 0.60.2", + "windows-sys 0.52.0", "x11rb", ] @@ -339,6 +348,15 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + [[package]] name = "askama" version = "0.16.0" @@ -364,7 +382,7 @@ dependencies = [ "memchr", "proc-macro2", "quote", - "rustc-hash", + "rustc-hash 2.1.3", "serde", "serde_derive", "syn 2.0.119", @@ -385,7 +403,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" dependencies = [ - "rustc-hash", + "rustc-hash 2.1.3", "serde", "serde_derive", "unicode-ident", @@ -592,6 +610,21 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitcoin_hashes" version = "0.14.101" @@ -601,11 +634,20 @@ dependencies = [ "hex-conservative", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] [[package]] name = "bitvec" @@ -649,6 +691,12 @@ dependencies = [ "constant_time_eq 0.4.2", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.9.0" @@ -725,6 +773,20 @@ name = "bytemuck" version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] [[package]] name = "byteorder" @@ -915,6 +977,16 @@ dependencies = [ "error-code", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width 0.1.14", +] + [[package]] name = "colorchoice" version = "1.0.5" @@ -1021,6 +1093,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -1037,6 +1119,17 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1104,7 +1197,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags", + "bitflags 2.13.1", "crossterm_winapi", "derive_more 2.1.1", "document-features", @@ -1364,7 +1457,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", ] @@ -1525,7 +1618,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8" dependencies = [ - "foldhash", + "foldhash 0.2.0", "libm", "portable-atomic", "siphasher", @@ -1622,12 +1715,45 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foldhash" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -1865,6 +1991,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + [[package]] name = "getrandom" version = "0.4.3" @@ -1874,7 +2012,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.1", "wasm-bindgen", ] @@ -1889,6 +2027,17 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + [[package]] name = "glob" version = "0.3.4" @@ -1941,6 +2090,27 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + [[package]] name = "goblin" version = "0.8.2" @@ -1952,6 +2122,57 @@ dependencies = [ "scroll", ] +[[package]] +name = "gpu-alloc" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9" +dependencies = [ + "bitflags 2.13.1", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058" +dependencies = [ + "bitflags 2.13.1", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" +dependencies = [ + "log", + "presser", + "thiserror 1.0.69", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.13.1", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.13.1", +] + [[package]] name = "group" version = "0.13.0" @@ -2010,6 +2231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", + "foldhash 0.1.5", ] [[package]] @@ -2020,7 +2242,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", "serde", "serde_core", ] @@ -2033,7 +2255,7 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", ] [[package]] @@ -2063,6 +2285,12 @@ dependencies = [ "arrayvec 0.7.8", ] +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + [[package]] name = "hkdf" version = "0.12.4" @@ -2592,7 +2820,7 @@ dependencies = [ "parking_lot", "pin-project", "rand 0.8.7", - "rustc-hash", + "rustc-hash 2.1.3", "serde", "serde_json", "thiserror 1.0.69", @@ -2695,6 +2923,23 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "konst" version = "0.2.20" @@ -2716,12 +2961,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libm" version = "0.2.16" @@ -2782,7 +3043,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e752191d037c44ad111a8caa762921926658402f01cc1253f7bef2020ece4f5e" dependencies = [ - "bitflags", + "bitflags 2.13.1", ] [[package]] @@ -2842,6 +3103,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.2.0" @@ -2869,6 +3139,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "metal" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" +dependencies = [ + "bitflags 2.13.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + [[package]] name = "minicov" version = "0.3.8" @@ -2923,6 +3208,28 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" +[[package]] +name = "naga" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e380993072e52eef724eddfcde0ed013b0c023c3f0417336ed041aa9f076994e" +dependencies = [ + "arrayvec 0.7.8", + "bit-set", + "bitflags 2.13.1", + "cfg_aliases", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "rustc-hash 1.1.0", + "spirv", + "strum 0.26.3", + "termcolor", + "thiserror 2.0.19", + "unicode-xid", +] + [[package]] name = "nanoid" version = "0.4.0" @@ -2932,6 +3239,15 @@ dependencies = [ "rand 0.8.7", ] +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys 0.3.1", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -3021,6 +3337,15 @@ dependencies = [ "libc", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "objc2" version = "0.6.4" @@ -3036,7 +3361,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-core-graphics", "objc2-foundation", @@ -3048,7 +3373,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags", + "bitflags 2.13.1", "dispatch2", "objc2", ] @@ -3059,7 +3384,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags", + "bitflags 2.13.1", "dispatch2", "objc2", "objc2-core-foundation", @@ -3078,7 +3403,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", ] @@ -3089,7 +3414,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "objc2", "objc2-core-foundation", ] @@ -3124,6 +3449,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "p256" version = "0.13.2" @@ -3254,6 +3588,12 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "picosimd" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7823ffd00d2b55ebe51750a19f47f2a33cb1f1d135f5cba893379b81c4d44856" + [[package]] name = "pin-project" version = "1.1.13" @@ -3301,6 +3641,12 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + [[package]] name = "plain" version = "0.2.3" @@ -3313,7 +3659,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags", + "bitflags 2.13.1", "crc32fast", "fdeflate", "flate2", @@ -3321,39 +3667,117 @@ dependencies = [ ] [[package]] -name = "polling" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +name = "polkavm" +version = "0.37.0" +source = "git+https://github.com/paritytech/polkavm.git?rev=c160c13c3c29bf3219ce1404ec95976000235a94#c160c13c3c29bf3219ce1404ec95976000235a94" dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix", - "windows-sys 0.61.2", + "libc", + "log", + "picosimd", + "polkavm-assembler", + "polkavm-common", + "polkavm-linux-raw", ] [[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +name = "polkavm-assembler" +version = "0.37.0" +source = "git+https://github.com/paritytech/polkavm.git?rev=c160c13c3c29bf3219ce1404ec95976000235a94#c160c13c3c29bf3219ce1404ec95976000235a94" dependencies = [ - "cpufeatures 0.2.17", - "opaque-debug", - "universal-hash", + "log", ] [[package]] -name = "portable-atomic" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" +name = "polkavm-common" +version = "0.37.0" +source = "git+https://github.com/paritytech/polkavm.git?rev=c160c13c3c29bf3219ce1404ec95976000235a94#c160c13c3c29bf3219ce1404ec95976000235a94" +dependencies = [ + "log", + "picosimd", + "polkavm-assembler", +] [[package]] -name = "potential_utf" -version = "0.1.5" +name = "polkavm-gpu-wire" +version = "0.2.0" +source = "git+https://github.com/paritytech/polkavm-host-runtime.git?rev=be1f15793e127cb5702d331fa8035bafc070c99a#be1f15793e127cb5702d331fa8035bafc070c99a" + +[[package]] +name = "polkavm-host-runtime" +version = "0.2.0" +source = "git+https://github.com/paritytech/polkavm-host-runtime.git?rev=be1f15793e127cb5702d331fa8035bafc070c99a#be1f15793e127cb5702d331fa8035bafc070c99a" +dependencies = [ + "anyhow", + "getrandom 0.3.4", + "log", + "polkavm", + "polkavm-gpu-wire", + "polkavm-motion-wire", + "polkavm-ui-wire", + "pollster", + "serde", + "serde_json", + "thiserror 1.0.69", + "uniffi", + "wasm-encoder", + "wgpu", +] + +[[package]] +name = "polkavm-linux-raw" +version = "0.37.0" +source = "git+https://github.com/paritytech/polkavm.git?rev=c160c13c3c29bf3219ce1404ec95976000235a94#c160c13c3c29bf3219ce1404ec95976000235a94" + +[[package]] +name = "polkavm-motion-wire" +version = "0.2.0" +source = "git+https://github.com/paritytech/polkavm-host-runtime.git?rev=be1f15793e127cb5702d331fa8035bafc070c99a#be1f15793e127cb5702d331fa8035bafc070c99a" + +[[package]] +name = "polkavm-ui-wire" +version = "0.2.0" +source = "git+https://github.com/paritytech/polkavm-host-runtime.git?rev=be1f15793e127cb5702d331fa8035bafc070c99a#be1f15793e127cb5702d331fa8035bafc070c99a" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + +[[package]] +name = "potential_utf" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ @@ -3375,6 +3799,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "primeorder" version = "0.13.6" @@ -3437,6 +3867,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" + [[package]] name = "pxfm" version = "0.1.30" @@ -3466,7 +3902,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.1.3", "rustls", "socket2", "thiserror 2.0.19", @@ -3487,7 +3923,7 @@ dependencies = [ "rand 0.10.2", "rand_pcg", "ring", - "rustc-hash", + "rustc-hash 2.1.3", "rustls", "rustls-pki-types", "slab", @@ -3520,6 +3956,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r-efi" version = "6.0.0" @@ -3588,6 +4030,12 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + [[package]] name = "ratatui" version = "0.30.2" @@ -3607,7 +4055,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags", + "bitflags 2.13.1", "compact_str", "hashbrown 0.17.1", "itertools 0.14.0", @@ -3615,11 +4063,11 @@ dependencies = [ "lru 0.18.2", "palette", "serde", - "strum", + "strum 0.28.0", "thiserror 2.0.19", "unicode-segmentation", "unicode-truncate", - "unicode-width", + "unicode-width 0.2.2", ] [[package]] @@ -3640,7 +4088,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags", + "bitflags 2.13.1", "hashbrown 0.17.1", "indoc", "instability", @@ -3648,12 +4096,18 @@ dependencies = [ "line-clipping", "ratatui-core", "serde", - "strum", + "strum 0.28.0", "time", "unicode-segmentation", - "unicode-width", + "unicode-width 0.2.2", ] +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "rayon" version = "1.12.0" @@ -3680,7 +4134,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.1", ] [[package]] @@ -3700,6 +4154,12 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + [[package]] name = "reqwest" version = "0.12.28" @@ -3768,6 +4228,12 @@ dependencies = [ "lru 0.16.4", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.3" @@ -3795,7 +4261,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", @@ -3845,7 +4311,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni", "log", @@ -3857,7 +4323,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs 0.26.11", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4127,8 +4593,8 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", - "core-foundation", + "bitflags 2.13.1", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -4371,6 +4837,15 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + [[package]] name = "smallstr" version = "0.3.1" @@ -4588,6 +5063,15 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.13.1", +] + [[package]] name = "spki" version = "0.7.3" @@ -4616,13 +5100,35 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + [[package]] name = "strum" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ - "strum_macros", + "strum_macros 0.28.0", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.119", ] [[package]] @@ -4899,6 +5405,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.16.2" @@ -5205,7 +5720,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags", + "bitflags 2.13.1", "bytes", "futures-util", "http", @@ -5304,6 +5819,14 @@ dependencies = [ "uniffi", ] +[[package]] +name = "truapi-client" +version = "0.13.1" +dependencies = [ + "parity-scale-codec", + "truapi", +] + [[package]] name = "truapi-codegen" version = "0.1.0" @@ -5358,7 +5881,7 @@ dependencies = [ "truapi", "truapi-platform", "truapi-server", - "unicode-width", + "unicode-width 0.2.2", "zeroize", ] @@ -5386,6 +5909,14 @@ dependencies = [ "zeroize", ] +[[package]] +name = "truapi-polkavm-host" +version = "0.2.0" +dependencies = [ + "polkavm-host-runtime", + "truapi-server", +] + [[package]] name = "truapi-provider" version = "0.1.0" @@ -5590,9 +6121,15 @@ checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ "itertools 0.14.0", "unicode-segmentation", - "unicode-width", + "unicode-width 0.2.2", ] +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode-width" version = "0.2.2" @@ -5887,6 +6424,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.126" @@ -5981,6 +6527,16 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c31d56021e873866c968588ed85ccdf56db5c426e44afdb4618c39895104b920" +[[package]] +name = "wasm-encoder" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d642d8c5ecc083aafe9ceb32809276a304547a3a6eeecceb5d8152598bc71f" +dependencies = [ + "leb128fmt", + "wasmparser 0.240.0", +] + [[package]] name = "wasmi" version = "0.40.0" @@ -5994,7 +6550,7 @@ dependencies = [ "wasmi_collections", "wasmi_core", "wasmi_ir", - "wasmparser", + "wasmparser 0.221.3", ] [[package]] @@ -6028,7 +6584,18 @@ version = "0.221.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185" dependencies = [ - "bitflags", + "bitflags 2.13.1", +] + +[[package]] +name = "wasmparser" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b722dcf61e0ea47440b53ff83ccb5df8efec57a69d150e4f24882e4eba7e24a4" +dependencies = [ + "bitflags 2.13.1", + "indexmap", + "semver", ] [[package]] @@ -6102,6 +6669,115 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +[[package]] +name = "wgpu" +version = "24.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0b3436f0729f6cdf2e6e9201f3d39dc95813fad61d826c1ed07918b4539353" +dependencies = [ + "arrayvec 0.7.8", + "bitflags 2.13.1", + "cfg_aliases", + "document-features", + "js-sys", + "log", + "naga", + "parking_lot", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "24.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f0aa306497a238d169b9dc70659105b4a096859a34894544ca81719242e1499" +dependencies = [ + "arrayvec 0.7.8", + "bit-vec", + "bitflags 2.13.1", + "cfg_aliases", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 2.0.19", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "24.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f112f464674ca69f3533248508ee30cb84c67cf06c25ff6800685f5e0294e259" +dependencies = [ + "android_system_properties", + "arrayvec 0.7.8", + "ash", + "bit-set", + "bitflags 2.13.1", + "block", + "bytemuck", + "cfg_aliases", + "core-graphics-types", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-allocator", + "gpu-descriptor", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "ordered-float", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "renderdoc-sys", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 2.0.19", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-types" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c" +dependencies = [ + "bitflags 2.13.1", + "js-sys", + "log", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -6133,6 +6809,51 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "windows-link" version = "0.2.1" @@ -6140,39 +6861,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-result" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.52.6", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-strings" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ + "windows-result", "windows-targets 0.52.6", ] [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.42.2", ] [[package]] name = "windows-sys" -version = "0.60.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.53.5", + "windows-targets 0.52.6", ] [[package]] @@ -6208,30 +6930,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -6244,12 +6949,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -6262,12 +6961,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -6280,24 +6973,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -6310,12 +6991,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -6328,12 +7003,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -6346,12 +7015,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -6364,12 +7027,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "1.0.4" @@ -6379,6 +7036,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "writeable" version = "0.6.3" @@ -6433,6 +7096,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "xml-rs" +version = "0.8.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" + [[package]] name = "yap" version = "0.12.0" diff --git a/README.md b/README.md index c7b032e4f..6ecc3bf15 100644 --- a/README.md +++ b/README.md @@ -65,11 +65,13 @@ See [`js/packages/truapi/README.md`](js/packages/truapi/README.md) for the full ``` rust/crates/ truapi/ Rust traits, versioned envelopes, and latest payload re-exports + truapi-client/ generated transport-neutral no-std client codecs and execution catalogs truapi-codegen/ rustdoc JSON to TypeScript client + Rust dispatcher truapi-macros/ #[wire(id = N)] proc-macro truapi-platform/ Host syscall traits used by truapi-server (storage, navigation, consent, ...) truapi-provider/ Network provider backends (WebSocket RPC or smoldot light-client) truapi-server/ Host runtime: dispatcher, typed SCALE logic, chain signing, WASM surface + truapi-polkavm-host/ Optional native composition of truapi-server and a pinned PolkaVM runtime js/packages/ truapi/ @parity/truapi TypeScript client truapi-host/ @parity/truapi-host: WASM-backed host runtime; entries `.` @@ -92,6 +94,14 @@ scripts/codegen.sh Regenerate the TS client from the Rust source scripts/battery.sh Run the generated battery against both headless CLI host roles ``` +The PolkaVM application runtime, GPU/UI wire contracts, and browser runtime +live in +[`paritytech/polkavm-host-runtime`](https://github.com/paritytech/polkavm-host-runtime). +Native hosts that need both runtimes link the optional `truapi-polkavm-host` +composition crate; the base `truapi-server` remains PolkaVM-free. Browser hosts +consume `@parity/polkavm-browser-runtime` directly; browser assets are not +shipped from this repository. + The Swift host adapter (the `TrUAPIHost` SPM package over the truapi-server UniFFI core) lives under [`ios/truapi-host/`](ios/truapi-host), with its SPM manifest at the repo root (`Package.swift`) so apps can consume it as a git-URL @@ -147,8 +157,8 @@ control of quota and of whether the bytes are backed up or encrypted. ## How it works 1. The protocol is defined as Rust traits in [`rust/crates/truapi/`](rust/crates/truapi/), with each method tagged `#[wire(id = N)]` for a stable byte-level dispatch table. Every method's doc comment must carry a ` ```ts ` example, which codegen extracts into the playground's EXAMPLE tab; the build fails if any method is missing one. -2. `truapi-codegen` reads rustdoc JSON for that crate and generates the TypeScript client under git-ignored paths in `js/packages/truapi/`. -3. Higher-level SDKs wrap the typed client; the transport encodes SCALE frames and ships them over `MessagePort` (or `postMessage` in iframe mode) to the host. +2. `truapi-codegen` reads rustdoc JSON for that crate and generates the TypeScript client, Rust host dispatcher, and the transport-neutral `no_std` Rust client. The Rust client exports typed method markers plus complete App, Widget, Worker, and Worker-only catalogs from the same wire schema. +3. Higher-level SDKs wrap the generated client; each runtime provides only its native frame transport. Browser products use `MessagePort` (or `postMessage` in iframe mode), while sandboxed runtimes such as PolkaVM supply explicit host imports. 4. The host decodes the frame, dispatches to the matching trait method, encodes the response, and ships it back. Wire ids are append-only: existing ids never change, so deployed products stay compatible across protocol revisions. Discriminant 255 is permanently reserved for a correlated protocol error, allowing either peer to reject API messages introduced after it was released instead of leaving the caller pending. diff --git a/deny.toml b/deny.toml index 1a454ec77..e76a7185f 100644 --- a/deny.toml +++ b/deny.toml @@ -41,6 +41,12 @@ exceptions = [ # BSL-1.0 is permissive, but scope it so it cannot spread to other crates. { name = "clipboard-win", allow = ["BSL-1.0"] }, { name = "error-code", allow = ["BSL-1.0"] }, + # The host-neutral PolkaVM runtime and wire protocols are intentionally + # MPL-2.0 so their Rust implementations retain file-level copyleft. + { name = "polkavm-gpu-wire", allow = ["MPL-2.0"] }, + { name = "polkavm-motion-wire", allow = ["MPL-2.0"] }, + { name = "polkavm-ui-wire", allow = ["MPL-2.0"] }, + { name = "polkavm-host-runtime", allow = ["MPL-2.0"] }, { name = "uniffi", allow = ["MPL-2.0"] }, { name = "uniffi_bindgen", allow = ["MPL-2.0"] }, { name = "uniffi_checksum_derive", allow = ["MPL-2.0"] }, diff --git a/docs/issue-drafts/pointer-capture-control.md b/docs/issue-drafts/pointer-capture-control.md new file mode 100644 index 000000000..509573f68 --- /dev/null +++ b/docs/issue-drafts/pointer-capture-control.md @@ -0,0 +1,146 @@ +# Add host-mediated pointer capture to TrUAPI + +## Status + +Parked prototype note. Do not start an RFC or implementation from this draft +yet. Current hosts capture non-Tri2D surfaces after a primary click, which is +sufficient for the existing game prototypes. Revisit only after prototypes +demonstrate that products need runtime capture/release control beyond the +host's click-to-capture and Escape-to-release policy. + +## Summary + +Pointer lock is host functionality. A product should request and release it through TrUAPI rather than declaring a separate `relative-pointer` feature in its manifest. The host owns the application surface, enforces user activation, calls the platform pointer-lock API, and reports lifecycle changes. High-frequency movement remains on the bounded device-input data path. + +This separates three concerns: + +- The App manifest declares ordinary `pointer` input support. +- TrUAPI controls whether pointer lock is free, armed, or captured. +- Request denial is a call error, and an older host reports the protocol's + standard unsupported-method error. +- The runtime input ABI delivers absolute positions while free and relative + deltas while captured. + +## Motivation + +Graphics profile is not a pointer policy. Some framebuffer and WebGPU products are first-person games that need unbounded relative motion; others are cursor-driven tools that must leave the system pointer free. Defaulting all non-Tri2D surfaces to pointer lock surprises cursor-driven products, while a static manifest feature cannot express when a mixed menu/game product wants capture. + +Pointer lock also cannot be delegated to sandboxed product code. Browser and native hosts own the trusted surface and must preserve an unconditional escape path. + +## Proposed control plane + +Names are placeholders for the RFC: + +```ts +input.pointerCapture.request(): Promise> + +input.pointerCapture.release(): Promise> + +input.pointerCapture.subscribe(): Subscription< + \"free\" | \"armed\" | \"captured\" +> +``` + +The subscription follows the existing `theme.subscribe()` and +`locale.subscribe()` convention: it emits the current state immediately and +then every transition. A separate `status()` request would duplicate the first +subscription item. + +A browser generally cannot honor `request()` immediately because pointer lock +requires a transient user activation. In that case `request()` returns +`armed`; the host acquires lock on the next eligible primary click on the +requesting product's active surface. + +`release()` is idempotent and always permitted. Escape always releases capture +and is consumed by the host for that transition rather than forwarded to the +product as a key press. + +`denied` is a request error rather than a durable capture state: after denial +the surface remains `free`. A host that predates these methods already has a +standard answer—the TrUAPI protocol-error frame for an unknown discriminant—so +`unsupported` does not belong in the domain state enum. + +## Fit with the existing TrUAPI architecture + +The API should be a small `Input` method group, backed by an optional +`PointerCaptureHost` platform callback. The TrUAPI server is product-scoped, so +the callback already runs in the identity and lifecycle context of the calling +product. Web, desktop, and other surface-owning hosts implement the callback; +CLI or non-pointer hosts omit it and receive the existing `Unsupported` +behavior. + +This should not be added to `HostDevicePermissionRequest`. RFC 0002 defines +device permission decisions as indefinitely persisted grants or denials, often +paired with an operating-system permission. Pointer lock is transient surface +state, requires a current user gesture, and must always be releasable. A future +host policy may gate the request, but the first API does not need a persisted +permission. + +The RFC must allocate new append-only wire discriminants for request, release, +and the subscription lifecycle. Existing discriminants cannot be reused. + +## Input data plane + +Pointer movement does not travel through TrUAPI. The existing bounded runtime input channel remains the data plane: + +- Free pointer: event type `5`, absolute canvas `x`/`y`. +- Captured pointer: event type `6`, signed relative `dx`/`dy`. +- Buttons: event types `3` and `4` in either state. + +Hosts should discard the first cursor-warp sample after lock acquisition, reject non-finite or implausible discontinuities, and coalesce high-rate deltas to the runtime's bounded update cadence. + +The browser operation is Pointer Lock (`requestPointerLock()`), not DOM pointer capture (`setPointerCapture()`). DOM pointer capture only preserves event routing during a drag and does not provide an unbounded relative pointer. + +## Host invariants + +- Pointer lock defaults to off for every graphics profile. +- Only the product bound to the active verified surface may request capture. +- Capture requires a real user gesture on that surface. +- A product cannot suppress Escape release. +- Losing focus, replacing the product, navigating, or destroying the surface releases capture. +- Relative events are emitted only while the surface actually owns pointer lock. +- Request denial and every state transition are observable by the product so it + can stop mouse-look or present fallback controls. +- Hosts that predate the API return TrUAPI's standard unsupported-method error; + products decide whether keyboard, touch, or controller input is an acceptable + fallback. + +## Manifest relationship + +No separate `relative-pointer` manifest feature is required. TrUAPI already +provides generic unsupported-method handling, the runtime request expresses +current intent, and the host remains the authority. + +A future RFC may revisit install-time metadata if hosts need to warn that a product cannot function without pointer lock. Such metadata would describe compatibility or user experience; it would not replace runtime request/release control. + +## Future user policy + +A host may eventually expose a per-product policy such as `Ask`, `Allow`, or `Block`, plus a global `Never allow pointer lock` setting. This is intentionally deferred. + +If added, the setting should authorize or deny product requests; it should not force an arbitrary cursor-driven product into relative mode. The policy should be scoped to a verified product identity, show a visible capture indicator, and preserve Escape as an unconditional release path. + +## Revisit criteria + +Keep the existing host behavior while prototypes mature. Promote this note to +an RFC only when at least one real product demonstrates a concrete need such +as: + +- a cursor-driven framebuffer or WebGPU surface that must never capture; +- a mixed menu/game product that must release and reacquire capture without + relying on Escape and a new click; +- a cross-host inconsistency that cannot be fixed as host policy; +- a product that needs to observe capture denial or loss to provide a usable + fallback. + +If one of those cases appears, the RFC should specify request, release, the +immediate state subscription, wire ids, user-gesture semantics, and errors. +Only after that should the shared Rust core, host callbacks, Epoca, Dotli, and +products be changed. + +## Unresolved questions + +- Whether `request()` should be a one-shot request or remain armed across Escape release until the product cancels it. +- Whether capture permission persists per product, per publisher, per artifact version, or only for the current session. +- Whether native hosts need a distinct result for operating-system policy denial. +- Whether products need an optional install-time declaration that pointer lock is essential rather than merely supported. +- Whether a host should expose a standard visual indicator or leave presentation to each host implementation. diff --git a/rust/crates/truapi-client/Cargo.toml b/rust/crates/truapi-client/Cargo.toml new file mode 100644 index 000000000..3aaa6fa5e --- /dev/null +++ b/rust/crates/truapi-client/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "truapi-client" +version = "0.13.1" +edition.workspace = true +license.workspace = true +description = "Transport-neutral no-std TrUAPI client codecs and generated method catalog" +publish = false + +[dependencies] +parity-scale-codec = { version = "3", default-features = false } +truapi = { path = "../truapi", default-features = false } + +[lints] +workspace = true diff --git a/rust/crates/truapi-client/src/generated.rs b/rust/crates/truapi-client/src/generated.rs new file mode 100644 index 000000000..5aca53c9d --- /dev/null +++ b/rust/crates/truapi-client/src/generated.rs @@ -0,0 +1,2338 @@ +//! Canonical TrUAPI client method catalog. +//! +//! Auto-generated by truapi-codegen. Do not edit. + +use super::*; + +/// Fingerprint of the generated wire contract. +pub const TRUAPI_WIRE_SCHEMA_HASH: &str = "0449982638d57658"; + +/// `account_connection_status_subscribe` method marker. +pub struct AccountConnectionStatusSubscribe; +impl AccountConnectionStatusSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "connection_status_subscribe", + wire_name: "account_connection_status_subscribe", + request_type: "()", + response_type: "truapi::versioned::account::HostAccountConnectionStatusSubscribeItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 18, + stop_id: 19, + interrupt_id: 20, + receive_id: 21, + }), + }; +} +impl SubscriptionMethod for AccountConnectionStatusSubscribe { + type Request = (); + type Item = truapi::versioned::account::HostAccountConnectionStatusSubscribeItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_get_account` method marker. +pub struct AccountGetAccount; +impl AccountGetAccount { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "get_account", + wire_name: "account_get_account", + request_type: "truapi::versioned::account::HostAccountGetRequest", + response_type: "truapi::versioned::account::HostAccountGetResponse", + error_type: Some("truapi::versioned::account::HostAccountGetError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 22, + response_id: 23, + }), + }; +} +impl RequestMethod for AccountGetAccount { + type Request = truapi::versioned::account::HostAccountGetRequest; + type Response = truapi::versioned::account::HostAccountGetResponse; + type Error = truapi::versioned::account::HostAccountGetError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_get_account_alias` method marker. +pub struct AccountGetAccountAlias; +impl AccountGetAccountAlias { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "get_account_alias", + wire_name: "account_get_account_alias", + request_type: "truapi::versioned::account::HostAccountGetAliasRequest", + response_type: "truapi::versioned::account::HostAccountGetAliasResponse", + error_type: Some("truapi::versioned::account::HostAccountGetAliasError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 24, + response_id: 25, + }), + }; +} +impl RequestMethod for AccountGetAccountAlias { + type Request = truapi::versioned::account::HostAccountGetAliasRequest; + type Response = truapi::versioned::account::HostAccountGetAliasResponse; + type Error = truapi::versioned::account::HostAccountGetAliasError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_create_account_proof` method marker. +pub struct AccountCreateAccountProof; +impl AccountCreateAccountProof { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "create_account_proof", + wire_name: "account_create_account_proof", + request_type: "truapi::versioned::account::HostAccountCreateProofRequest", + response_type: "truapi::versioned::account::HostAccountCreateProofResponse", + error_type: Some("truapi::versioned::account::HostAccountCreateProofError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 26, + response_id: 27, + }), + }; +} +impl RequestMethod for AccountCreateAccountProof { + type Request = truapi::versioned::account::HostAccountCreateProofRequest; + type Response = truapi::versioned::account::HostAccountCreateProofResponse; + type Error = truapi::versioned::account::HostAccountCreateProofError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_sign_vrf` method marker. +pub struct AccountSignVrf; +impl AccountSignVrf { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "sign_vrf", + wire_name: "account_sign_vrf", + request_type: "truapi::versioned::account::HostAccountSignVrfRequest", + response_type: "truapi::versioned::account::HostAccountSignVrfResponse", + error_type: Some("truapi::versioned::account::HostAccountSignVrfError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 164, + response_id: 165, + }), + }; +} +impl RequestMethod for AccountSignVrf { + type Request = truapi::versioned::account::HostAccountSignVrfRequest; + type Response = truapi::versioned::account::HostAccountSignVrfResponse; + type Error = truapi::versioned::account::HostAccountSignVrfError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_register_ring_vrf_key` method marker. +pub struct AccountRegisterRingVrfKey; +impl AccountRegisterRingVrfKey { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "register_ring_vrf_key", + wire_name: "account_register_ring_vrf_key", + request_type: "truapi::versioned::account::HostAccountRegisterRingVrfKeyRequest", + response_type: "truapi::versioned::account::HostAccountRegisterRingVrfKeyResponse", + error_type: Some("truapi::versioned::account::HostAccountRegisterRingVrfKeyError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 168, + response_id: 169, + }), + }; +} +impl RequestMethod for AccountRegisterRingVrfKey { + type Request = truapi::versioned::account::HostAccountRegisterRingVrfKeyRequest; + type Response = truapi::versioned::account::HostAccountRegisterRingVrfKeyResponse; + type Error = truapi::versioned::account::HostAccountRegisterRingVrfKeyError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_list_ring_vrf_keys` method marker. +pub struct AccountListRingVrfKeys; +impl AccountListRingVrfKeys { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "list_ring_vrf_keys", + wire_name: "account_list_ring_vrf_keys", + request_type: "truapi::versioned::account::HostAccountListRingVrfKeysRequest", + response_type: "truapi::versioned::account::HostAccountListRingVrfKeysResponse", + error_type: Some("truapi::versioned::account::HostAccountListRingVrfKeysError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 170, + response_id: 171, + }), + }; +} +impl RequestMethod for AccountListRingVrfKeys { + type Request = truapi::versioned::account::HostAccountListRingVrfKeysRequest; + type Response = truapi::versioned::account::HostAccountListRingVrfKeysResponse; + type Error = truapi::versioned::account::HostAccountListRingVrfKeysError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_ring_vrf_sign` method marker. +pub struct AccountRingVrfSign; +impl AccountRingVrfSign { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "ring_vrf_sign", + wire_name: "account_ring_vrf_sign", + request_type: "truapi::versioned::account::HostAccountRingVrfSignRequest", + response_type: "truapi::versioned::account::HostAccountRingVrfSignResponse", + error_type: Some("truapi::versioned::account::HostAccountRingVrfSignError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 172, + response_id: 173, + }), + }; +} +impl RequestMethod for AccountRingVrfSign { + type Request = truapi::versioned::account::HostAccountRingVrfSignRequest; + type Response = truapi::versioned::account::HostAccountRingVrfSignResponse; + type Error = truapi::versioned::account::HostAccountRingVrfSignError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_get_legacy_accounts` method marker. +pub struct AccountGetLegacyAccounts; +impl AccountGetLegacyAccounts { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "get_legacy_accounts", + wire_name: "account_get_legacy_accounts", + request_type: "truapi::versioned::account::HostGetLegacyAccountsRequest", + response_type: "truapi::versioned::account::HostGetLegacyAccountsResponse", + error_type: Some("truapi::versioned::account::HostGetLegacyAccountsError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 28, + response_id: 29, + }), + }; +} +impl RequestMethod for AccountGetLegacyAccounts { + type Request = truapi::versioned::account::HostGetLegacyAccountsRequest; + type Response = truapi::versioned::account::HostGetLegacyAccountsResponse; + type Error = truapi::versioned::account::HostGetLegacyAccountsError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_get_user_id` method marker. +pub struct AccountGetUserId; +impl AccountGetUserId { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "get_user_id", + wire_name: "account_get_user_id", + request_type: "truapi::versioned::account::HostGetUserIdRequest", + response_type: "truapi::versioned::account::HostGetUserIdResponse", + error_type: Some("truapi::versioned::account::HostGetUserIdError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 110, + response_id: 111, + }), + }; +} +impl RequestMethod for AccountGetUserId { + type Request = truapi::versioned::account::HostGetUserIdRequest; + type Response = truapi::versioned::account::HostGetUserIdResponse; + type Error = truapi::versioned::account::HostGetUserIdError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `account_request_login` method marker. +pub struct AccountRequestLogin; +impl AccountRequestLogin { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Account", + method: "request_login", + wire_name: "account_request_login", + request_type: "truapi::versioned::account::HostRequestLoginRequest", + response_type: "truapi::versioned::account::HostRequestLoginResponse", + error_type: Some("truapi::versioned::account::HostRequestLoginError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 112, + response_id: 113, + }), + }; +} +impl RequestMethod for AccountRequestLogin { + type Request = truapi::versioned::account::HostRequestLoginRequest; + type Response = truapi::versioned::account::HostRequestLoginResponse; + type Error = truapi::versioned::account::HostRequestLoginError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_follow_head_subscribe` method marker. +pub struct ChainFollowHeadSubscribe; +impl ChainFollowHeadSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "follow_head_subscribe", + wire_name: "chain_follow_head_subscribe", + request_type: "truapi::versioned::chain::RemoteChainHeadFollowRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadFollowItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 76, + stop_id: 77, + interrupt_id: 78, + receive_id: 79, + }), + }; +} +impl SubscriptionMethod for ChainFollowHeadSubscribe { + type Request = truapi::versioned::chain::RemoteChainHeadFollowRequest; + type Item = truapi::versioned::chain::RemoteChainHeadFollowItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_head_header` method marker. +pub struct ChainGetHeadHeader; +impl ChainGetHeadHeader { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_head_header", + wire_name: "chain_get_head_header", + request_type: "truapi::versioned::chain::RemoteChainHeadHeaderRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadHeaderResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadHeaderError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 80, + response_id: 81, + }), + }; +} +impl RequestMethod for ChainGetHeadHeader { + type Request = truapi::versioned::chain::RemoteChainHeadHeaderRequest; + type Response = truapi::versioned::chain::RemoteChainHeadHeaderResponse; + type Error = truapi::versioned::chain::RemoteChainHeadHeaderError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_head_body` method marker. +pub struct ChainGetHeadBody; +impl ChainGetHeadBody { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_head_body", + wire_name: "chain_get_head_body", + request_type: "truapi::versioned::chain::RemoteChainHeadBodyRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadBodyResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadBodyError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 82, + response_id: 83, + }), + }; +} +impl RequestMethod for ChainGetHeadBody { + type Request = truapi::versioned::chain::RemoteChainHeadBodyRequest; + type Response = truapi::versioned::chain::RemoteChainHeadBodyResponse; + type Error = truapi::versioned::chain::RemoteChainHeadBodyError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_head_storage` method marker. +pub struct ChainGetHeadStorage; +impl ChainGetHeadStorage { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_head_storage", + wire_name: "chain_get_head_storage", + request_type: "truapi::versioned::chain::RemoteChainHeadStorageRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadStorageResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadStorageError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 84, + response_id: 85, + }), + }; +} +impl RequestMethod for ChainGetHeadStorage { + type Request = truapi::versioned::chain::RemoteChainHeadStorageRequest; + type Response = truapi::versioned::chain::RemoteChainHeadStorageResponse; + type Error = truapi::versioned::chain::RemoteChainHeadStorageError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_call_head` method marker. +pub struct ChainCallHead; +impl ChainCallHead { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "call_head", + wire_name: "chain_call_head", + request_type: "truapi::versioned::chain::RemoteChainHeadCallRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadCallResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadCallError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 86, + response_id: 87, + }), + }; +} +impl RequestMethod for ChainCallHead { + type Request = truapi::versioned::chain::RemoteChainHeadCallRequest; + type Response = truapi::versioned::chain::RemoteChainHeadCallResponse; + type Error = truapi::versioned::chain::RemoteChainHeadCallError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_unpin_head` method marker. +pub struct ChainUnpinHead; +impl ChainUnpinHead { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "unpin_head", + wire_name: "chain_unpin_head", + request_type: "truapi::versioned::chain::RemoteChainHeadUnpinRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadUnpinResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadUnpinError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 88, + response_id: 89, + }), + }; +} +impl RequestMethod for ChainUnpinHead { + type Request = truapi::versioned::chain::RemoteChainHeadUnpinRequest; + type Response = truapi::versioned::chain::RemoteChainHeadUnpinResponse; + type Error = truapi::versioned::chain::RemoteChainHeadUnpinError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_continue_head` method marker. +pub struct ChainContinueHead; +impl ChainContinueHead { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "continue_head", + wire_name: "chain_continue_head", + request_type: "truapi::versioned::chain::RemoteChainHeadContinueRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadContinueResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadContinueError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 90, + response_id: 91, + }), + }; +} +impl RequestMethod for ChainContinueHead { + type Request = truapi::versioned::chain::RemoteChainHeadContinueRequest; + type Response = truapi::versioned::chain::RemoteChainHeadContinueResponse; + type Error = truapi::versioned::chain::RemoteChainHeadContinueError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_stop_head_operation` method marker. +pub struct ChainStopHeadOperation; +impl ChainStopHeadOperation { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "stop_head_operation", + wire_name: "chain_stop_head_operation", + request_type: "truapi::versioned::chain::RemoteChainHeadStopOperationRequest", + response_type: "truapi::versioned::chain::RemoteChainHeadStopOperationResponse", + error_type: Some("truapi::versioned::chain::RemoteChainHeadStopOperationError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 92, + response_id: 93, + }), + }; +} +impl RequestMethod for ChainStopHeadOperation { + type Request = truapi::versioned::chain::RemoteChainHeadStopOperationRequest; + type Response = truapi::versioned::chain::RemoteChainHeadStopOperationResponse; + type Error = truapi::versioned::chain::RemoteChainHeadStopOperationError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_spec_genesis_hash` method marker. +pub struct ChainGetSpecGenesisHash; +impl ChainGetSpecGenesisHash { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_spec_genesis_hash", + wire_name: "chain_get_spec_genesis_hash", + request_type: "truapi::versioned::chain::RemoteChainSpecGenesisHashRequest", + response_type: "truapi::versioned::chain::RemoteChainSpecGenesisHashResponse", + error_type: Some("truapi::versioned::chain::RemoteChainSpecGenesisHashError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 94, + response_id: 95, + }), + }; +} +impl RequestMethod for ChainGetSpecGenesisHash { + type Request = truapi::versioned::chain::RemoteChainSpecGenesisHashRequest; + type Response = truapi::versioned::chain::RemoteChainSpecGenesisHashResponse; + type Error = truapi::versioned::chain::RemoteChainSpecGenesisHashError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_spec_chain_name` method marker. +pub struct ChainGetSpecChainName; +impl ChainGetSpecChainName { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_spec_chain_name", + wire_name: "chain_get_spec_chain_name", + request_type: "truapi::versioned::chain::RemoteChainSpecChainNameRequest", + response_type: "truapi::versioned::chain::RemoteChainSpecChainNameResponse", + error_type: Some("truapi::versioned::chain::RemoteChainSpecChainNameError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 96, + response_id: 97, + }), + }; +} +impl RequestMethod for ChainGetSpecChainName { + type Request = truapi::versioned::chain::RemoteChainSpecChainNameRequest; + type Response = truapi::versioned::chain::RemoteChainSpecChainNameResponse; + type Error = truapi::versioned::chain::RemoteChainSpecChainNameError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_spec_properties` method marker. +pub struct ChainGetSpecProperties; +impl ChainGetSpecProperties { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_spec_properties", + wire_name: "chain_get_spec_properties", + request_type: "truapi::versioned::chain::RemoteChainSpecPropertiesRequest", + response_type: "truapi::versioned::chain::RemoteChainSpecPropertiesResponse", + error_type: Some("truapi::versioned::chain::RemoteChainSpecPropertiesError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 98, + response_id: 99, + }), + }; +} +impl RequestMethod for ChainGetSpecProperties { + type Request = truapi::versioned::chain::RemoteChainSpecPropertiesRequest; + type Response = truapi::versioned::chain::RemoteChainSpecPropertiesResponse; + type Error = truapi::versioned::chain::RemoteChainSpecPropertiesError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_broadcast_transaction` method marker. +pub struct ChainBroadcastTransaction; +impl ChainBroadcastTransaction { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "broadcast_transaction", + wire_name: "chain_broadcast_transaction", + request_type: "truapi::versioned::chain::RemoteChainTransactionBroadcastRequest", + response_type: "truapi::versioned::chain::RemoteChainTransactionBroadcastResponse", + error_type: Some("truapi::versioned::chain::RemoteChainTransactionBroadcastError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 100, + response_id: 101, + }), + }; +} +impl RequestMethod for ChainBroadcastTransaction { + type Request = truapi::versioned::chain::RemoteChainTransactionBroadcastRequest; + type Response = truapi::versioned::chain::RemoteChainTransactionBroadcastResponse; + type Error = truapi::versioned::chain::RemoteChainTransactionBroadcastError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_stop_transaction` method marker. +pub struct ChainStopTransaction; +impl ChainStopTransaction { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "stop_transaction", + wire_name: "chain_stop_transaction", + request_type: "truapi::versioned::chain::RemoteChainTransactionStopRequest", + response_type: "truapi::versioned::chain::RemoteChainTransactionStopResponse", + error_type: Some("truapi::versioned::chain::RemoteChainTransactionStopError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 102, + response_id: 103, + }), + }; +} +impl RequestMethod for ChainStopTransaction { + type Request = truapi::versioned::chain::RemoteChainTransactionStopRequest; + type Response = truapi::versioned::chain::RemoteChainTransactionStopResponse; + type Error = truapi::versioned::chain::RemoteChainTransactionStopError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chain_get_chain_info` method marker. +pub struct ChainGetChainInfo; +impl ChainGetChainInfo { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chain", + method: "get_chain_info", + wire_name: "chain_get_chain_info", + request_type: "truapi::versioned::chain::RemoteChainInfoRequest", + response_type: "truapi::versioned::chain::RemoteChainInfoResponse", + error_type: Some("truapi::versioned::chain::RemoteChainInfoError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 166, + response_id: 167, + }), + }; +} +impl RequestMethod for ChainGetChainInfo { + type Request = truapi::versioned::chain::RemoteChainInfoRequest; + type Response = truapi::versioned::chain::RemoteChainInfoResponse; + type Error = truapi::versioned::chain::RemoteChainInfoError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chat_create_room` method marker. +pub struct ChatCreateRoom; +impl ChatCreateRoom { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chat", + method: "create_room", + wire_name: "chat_create_room", + request_type: "truapi::versioned::chat::HostChatCreateRoomRequest", + response_type: "truapi::versioned::chat::HostChatCreateRoomResponse", + error_type: Some("truapi::versioned::chat::HostChatCreateRoomError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: Some(ExecutionKind::Worker), + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 38, + response_id: 39, + }), + }; +} +impl RequestMethod for ChatCreateRoom { + type Request = truapi::versioned::chat::HostChatCreateRoomRequest; + type Response = truapi::versioned::chat::HostChatCreateRoomResponse; + type Error = truapi::versioned::chat::HostChatCreateRoomError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chat_register_bot` method marker. +pub struct ChatRegisterBot; +impl ChatRegisterBot { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chat", + method: "register_bot", + wire_name: "chat_register_bot", + request_type: "truapi::versioned::chat::HostChatRegisterBotRequest", + response_type: "truapi::versioned::chat::HostChatRegisterBotResponse", + error_type: Some("truapi::versioned::chat::HostChatRegisterBotError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: Some(ExecutionKind::Worker), + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 40, + response_id: 41, + }), + }; +} +impl RequestMethod for ChatRegisterBot { + type Request = truapi::versioned::chat::HostChatRegisterBotRequest; + type Response = truapi::versioned::chat::HostChatRegisterBotResponse; + type Error = truapi::versioned::chat::HostChatRegisterBotError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chat_list_subscribe` method marker. +pub struct ChatListSubscribe; +impl ChatListSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chat", + method: "list_subscribe", + wire_name: "chat_list_subscribe", + request_type: "()", + response_type: "truapi::versioned::chat::HostChatListSubscribeItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: Some(ExecutionKind::Worker), + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 42, + stop_id: 43, + interrupt_id: 44, + receive_id: 45, + }), + }; +} +impl SubscriptionMethod for ChatListSubscribe { + type Request = (); + type Item = truapi::versioned::chat::HostChatListSubscribeItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chat_post_message` method marker. +pub struct ChatPostMessage; +impl ChatPostMessage { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chat", + method: "post_message", + wire_name: "chat_post_message", + request_type: "truapi::versioned::chat::HostChatPostMessageRequest", + response_type: "truapi::versioned::chat::HostChatPostMessageResponse", + error_type: Some("truapi::versioned::chat::HostChatPostMessageError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: Some(ExecutionKind::Worker), + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 46, + response_id: 47, + }), + }; +} +impl RequestMethod for ChatPostMessage { + type Request = truapi::versioned::chat::HostChatPostMessageRequest; + type Response = truapi::versioned::chat::HostChatPostMessageResponse; + type Error = truapi::versioned::chat::HostChatPostMessageError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chat_action_subscribe` method marker. +pub struct ChatActionSubscribe; +impl ChatActionSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chat", + method: "action_subscribe", + wire_name: "chat_action_subscribe", + request_type: "()", + response_type: "truapi::versioned::chat::HostChatActionSubscribeItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: Some(ExecutionKind::Worker), + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 48, + stop_id: 49, + interrupt_id: 50, + receive_id: 51, + }), + }; +} +impl SubscriptionMethod for ChatActionSubscribe { + type Request = (); + type Item = truapi::versioned::chat::HostChatActionSubscribeItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `chat_custom_message_render` method marker. +pub struct ChatCustomMessageRender; +impl ChatCustomMessageRender { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Chat", + method: "custom_message_render", + wire_name: "chat_custom_message_render", + request_type: "truapi::versioned::chat::ProductChatCustomMessageRenderRequest", + response_type: "truapi::versioned::chat::ProductChatCustomMessageRenderItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::HostToProduct, + required_execution: Some(ExecutionKind::Worker), + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 52, + stop_id: 53, + interrupt_id: 54, + receive_id: 55, + }), + }; +} +impl HostSubscriptionMethod for ChatCustomMessageRender { + type Request = truapi::versioned::chat::ProductChatCustomMessageRenderRequest; + type Item = truapi::versioned::chat::ProductChatCustomMessageRenderItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_create_purse` method marker. +pub struct CoinPaymentCreatePurse; +impl CoinPaymentCreatePurse { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "create_purse", + wire_name: "coin_payment_create_purse", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentCreatePurseRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentCreatePurseResponse", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentCreatePurseError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 136, + response_id: 137, + }), + }; +} +impl RequestMethod for CoinPaymentCreatePurse { + type Request = truapi::versioned::coin_payment::HostCoinPaymentCreatePurseRequest; + type Response = truapi::versioned::coin_payment::HostCoinPaymentCreatePurseResponse; + type Error = truapi::versioned::coin_payment::HostCoinPaymentCreatePurseError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_query_purse` method marker. +pub struct CoinPaymentQueryPurse; +impl CoinPaymentQueryPurse { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "query_purse", + wire_name: "coin_payment_query_purse", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentQueryPurseRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentQueryPurseResponse", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentQueryPurseError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 138, + response_id: 139, + }), + }; +} +impl RequestMethod for CoinPaymentQueryPurse { + type Request = truapi::versioned::coin_payment::HostCoinPaymentQueryPurseRequest; + type Response = truapi::versioned::coin_payment::HostCoinPaymentQueryPurseResponse; + type Error = truapi::versioned::coin_payment::HostCoinPaymentQueryPurseError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_rebalance_purse` method marker. +pub struct CoinPaymentRebalancePurse; +impl CoinPaymentRebalancePurse { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "rebalance_purse", + wire_name: "coin_payment_rebalance_purse", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentRebalancePurseRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentRebalancePurseItem", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentRebalancePurseError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 140, + stop_id: 141, + interrupt_id: 142, + receive_id: 143, + }), + }; +} +impl ResultSubscriptionMethod for CoinPaymentRebalancePurse { + type Request = truapi::versioned::coin_payment::HostCoinPaymentRebalancePurseRequest; + type Item = truapi::versioned::coin_payment::HostCoinPaymentRebalancePurseItem; + type Error = truapi::versioned::coin_payment::HostCoinPaymentRebalancePurseError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_delete_purse` method marker. +pub struct CoinPaymentDeletePurse; +impl CoinPaymentDeletePurse { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "delete_purse", + wire_name: "coin_payment_delete_purse", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentDeletePurseRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentDeletePurseItem", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentDeletePurseError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 144, + stop_id: 145, + interrupt_id: 146, + receive_id: 147, + }), + }; +} +impl ResultSubscriptionMethod for CoinPaymentDeletePurse { + type Request = truapi::versioned::coin_payment::HostCoinPaymentDeletePurseRequest; + type Item = truapi::versioned::coin_payment::HostCoinPaymentDeletePurseItem; + type Error = truapi::versioned::coin_payment::HostCoinPaymentDeletePurseError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_create_receivable` method marker. +pub struct CoinPaymentCreateReceivable; +impl CoinPaymentCreateReceivable { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "create_receivable", + wire_name: "coin_payment_create_receivable", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentCreateReceivableRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentCreateReceivableResponse", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentCreateReceivableError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 148, + response_id: 149, + }), + }; +} +impl RequestMethod for CoinPaymentCreateReceivable { + type Request = truapi::versioned::coin_payment::HostCoinPaymentCreateReceivableRequest; + type Response = truapi::versioned::coin_payment::HostCoinPaymentCreateReceivableResponse; + type Error = truapi::versioned::coin_payment::HostCoinPaymentCreateReceivableError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_create_cheque` method marker. +pub struct CoinPaymentCreateCheque; +impl CoinPaymentCreateCheque { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "create_cheque", + wire_name: "coin_payment_create_cheque", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentCreateChequeRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentCreateChequeResponse", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentCreateChequeError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 150, + response_id: 151, + }), + }; +} +impl RequestMethod for CoinPaymentCreateCheque { + type Request = truapi::versioned::coin_payment::HostCoinPaymentCreateChequeRequest; + type Response = truapi::versioned::coin_payment::HostCoinPaymentCreateChequeResponse; + type Error = truapi::versioned::coin_payment::HostCoinPaymentCreateChequeError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_deposit` method marker. +pub struct CoinPaymentDeposit; +impl CoinPaymentDeposit { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "deposit", + wire_name: "coin_payment_deposit", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentDepositRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentDepositItem", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentDepositError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 152, + stop_id: 153, + interrupt_id: 154, + receive_id: 155, + }), + }; +} +impl ResultSubscriptionMethod for CoinPaymentDeposit { + type Request = truapi::versioned::coin_payment::HostCoinPaymentDepositRequest; + type Item = truapi::versioned::coin_payment::HostCoinPaymentDepositItem; + type Error = truapi::versioned::coin_payment::HostCoinPaymentDepositError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_refund` method marker. +pub struct CoinPaymentRefund; +impl CoinPaymentRefund { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "refund", + wire_name: "coin_payment_refund", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentRefundRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentRefundItem", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentRefundError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 156, + stop_id: 157, + interrupt_id: 158, + receive_id: 159, + }), + }; +} +impl ResultSubscriptionMethod for CoinPaymentRefund { + type Request = truapi::versioned::coin_payment::HostCoinPaymentRefundRequest; + type Item = truapi::versioned::coin_payment::HostCoinPaymentRefundItem; + type Error = truapi::versioned::coin_payment::HostCoinPaymentRefundError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `coin_payment_listen_for_payment` method marker. +pub struct CoinPaymentListenForPayment; +impl CoinPaymentListenForPayment { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "CoinPayment", + method: "listen_for_payment", + wire_name: "coin_payment_listen_for_payment", + request_type: "truapi::versioned::coin_payment::HostCoinPaymentListenForRequest", + response_type: "truapi::versioned::coin_payment::HostCoinPaymentListenForItem", + error_type: Some("truapi::versioned::coin_payment::HostCoinPaymentListenForError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 160, + stop_id: 161, + interrupt_id: 162, + receive_id: 163, + }), + }; +} +impl ResultSubscriptionMethod for CoinPaymentListenForPayment { + type Request = truapi::versioned::coin_payment::HostCoinPaymentListenForRequest; + type Item = truapi::versioned::coin_payment::HostCoinPaymentListenForItem; + type Error = truapi::versioned::coin_payment::HostCoinPaymentListenForError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `entropy_derive` method marker. +pub struct EntropyDerive; +impl EntropyDerive { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Entropy", + method: "derive", + wire_name: "entropy_derive", + request_type: "truapi::versioned::entropy::HostDeriveEntropyRequest", + response_type: "truapi::versioned::entropy::HostDeriveEntropyResponse", + error_type: Some("truapi::versioned::entropy::HostDeriveEntropyError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 108, + response_id: 109, + }), + }; +} +impl RequestMethod for EntropyDerive { + type Request = truapi::versioned::entropy::HostDeriveEntropyRequest; + type Response = truapi::versioned::entropy::HostDeriveEntropyResponse; + type Error = truapi::versioned::entropy::HostDeriveEntropyError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `local_storage_read` method marker. +pub struct LocalStorageRead; +impl LocalStorageRead { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "LocalStorage", + method: "read", + wire_name: "local_storage_read", + request_type: "truapi::versioned::local_storage::HostLocalStorageReadRequest", + response_type: "truapi::versioned::local_storage::HostLocalStorageReadResponse", + error_type: Some("truapi::versioned::local_storage::HostLocalStorageReadError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 12, + response_id: 13, + }), + }; +} +impl RequestMethod for LocalStorageRead { + type Request = truapi::versioned::local_storage::HostLocalStorageReadRequest; + type Response = truapi::versioned::local_storage::HostLocalStorageReadResponse; + type Error = truapi::versioned::local_storage::HostLocalStorageReadError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `local_storage_write` method marker. +pub struct LocalStorageWrite; +impl LocalStorageWrite { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "LocalStorage", + method: "write", + wire_name: "local_storage_write", + request_type: "truapi::versioned::local_storage::HostLocalStorageWriteRequest", + response_type: "truapi::versioned::local_storage::HostLocalStorageWriteResponse", + error_type: Some("truapi::versioned::local_storage::HostLocalStorageWriteError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 14, + response_id: 15, + }), + }; +} +impl RequestMethod for LocalStorageWrite { + type Request = truapi::versioned::local_storage::HostLocalStorageWriteRequest; + type Response = truapi::versioned::local_storage::HostLocalStorageWriteResponse; + type Error = truapi::versioned::local_storage::HostLocalStorageWriteError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `local_storage_clear` method marker. +pub struct LocalStorageClear; +impl LocalStorageClear { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "LocalStorage", + method: "clear", + wire_name: "local_storage_clear", + request_type: "truapi::versioned::local_storage::HostLocalStorageClearRequest", + response_type: "truapi::versioned::local_storage::HostLocalStorageClearResponse", + error_type: Some("truapi::versioned::local_storage::HostLocalStorageClearError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 16, + response_id: 17, + }), + }; +} +impl RequestMethod for LocalStorageClear { + type Request = truapi::versioned::local_storage::HostLocalStorageClearRequest; + type Response = truapi::versioned::local_storage::HostLocalStorageClearResponse; + type Error = truapi::versioned::local_storage::HostLocalStorageClearError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `locale_subscribe` method marker. +pub struct LocaleSubscribe; +impl LocaleSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Locale", + method: "subscribe", + wire_name: "locale_subscribe", + request_type: "()", + response_type: "truapi::versioned::locale::HostLocaleSubscribeItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 194, + stop_id: 195, + interrupt_id: 196, + receive_id: 197, + }), + }; +} +impl SubscriptionMethod for LocaleSubscribe { + type Request = (); + type Item = truapi::versioned::locale::HostLocaleSubscribeItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `notifications_send_push_notification` method marker. +pub struct NotificationsSendPushNotification; +impl NotificationsSendPushNotification { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Notifications", + method: "send_push_notification", + wire_name: "notifications_send_push_notification", + request_type: "truapi::versioned::notifications::HostPushNotificationRequest", + response_type: "truapi::versioned::notifications::HostPushNotificationResponse", + error_type: Some("truapi::versioned::notifications::HostPushNotificationError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 4, + response_id: 5, + }), + }; +} +impl RequestMethod for NotificationsSendPushNotification { + type Request = truapi::versioned::notifications::HostPushNotificationRequest; + type Response = truapi::versioned::notifications::HostPushNotificationResponse; + type Error = truapi::versioned::notifications::HostPushNotificationError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `notifications_cancel_push_notification` method marker. +pub struct NotificationsCancelPushNotification; +impl NotificationsCancelPushNotification { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Notifications", + method: "cancel_push_notification", + wire_name: "notifications_cancel_push_notification", + request_type: "truapi::versioned::notifications::HostPushNotificationCancelRequest", + response_type: "truapi::versioned::notifications::HostPushNotificationCancelResponse", + error_type: Some("truapi::versioned::notifications::HostPushNotificationCancelError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 134, + response_id: 135, + }), + }; +} +impl RequestMethod for NotificationsCancelPushNotification { + type Request = truapi::versioned::notifications::HostPushNotificationCancelRequest; + type Response = truapi::versioned::notifications::HostPushNotificationCancelResponse; + type Error = truapi::versioned::notifications::HostPushNotificationCancelError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `payment_balance_subscribe` method marker. +pub struct PaymentBalanceSubscribe; +impl PaymentBalanceSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Payment", + method: "balance_subscribe", + wire_name: "payment_balance_subscribe", + request_type: "truapi::versioned::payment::HostPaymentBalanceSubscribeRequest", + response_type: "truapi::versioned::payment::HostPaymentBalanceSubscribeItem", + error_type: Some("truapi::versioned::payment::HostPaymentBalanceSubscribeError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 118, + stop_id: 119, + interrupt_id: 120, + receive_id: 121, + }), + }; +} +impl ResultSubscriptionMethod for PaymentBalanceSubscribe { + type Request = truapi::versioned::payment::HostPaymentBalanceSubscribeRequest; + type Item = truapi::versioned::payment::HostPaymentBalanceSubscribeItem; + type Error = truapi::versioned::payment::HostPaymentBalanceSubscribeError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `payment_request` method marker. +pub struct PaymentRequest; +impl PaymentRequest { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Payment", + method: "request", + wire_name: "payment_request", + request_type: "truapi::versioned::payment::HostPaymentRequest", + response_type: "truapi::versioned::payment::HostPaymentResponse", + error_type: Some("truapi::versioned::payment::HostPaymentError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 124, + response_id: 125, + }), + }; +} +impl RequestMethod for PaymentRequest { + type Request = truapi::versioned::payment::HostPaymentRequest; + type Response = truapi::versioned::payment::HostPaymentResponse; + type Error = truapi::versioned::payment::HostPaymentError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `payment_status_subscribe` method marker. +pub struct PaymentStatusSubscribe; +impl PaymentStatusSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Payment", + method: "status_subscribe", + wire_name: "payment_status_subscribe", + request_type: "truapi::versioned::payment::HostPaymentStatusSubscribeRequest", + response_type: "truapi::versioned::payment::HostPaymentStatusSubscribeItem", + error_type: Some("truapi::versioned::payment::HostPaymentStatusSubscribeError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 126, + stop_id: 127, + interrupt_id: 128, + receive_id: 129, + }), + }; +} +impl ResultSubscriptionMethod for PaymentStatusSubscribe { + type Request = truapi::versioned::payment::HostPaymentStatusSubscribeRequest; + type Item = truapi::versioned::payment::HostPaymentStatusSubscribeItem; + type Error = truapi::versioned::payment::HostPaymentStatusSubscribeError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `payment_top_up` method marker. +pub struct PaymentTopUp; +impl PaymentTopUp { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Payment", + method: "top_up", + wire_name: "payment_top_up", + request_type: "truapi::versioned::payment::HostPaymentTopUpRequest", + response_type: "truapi::versioned::payment::HostPaymentTopUpResponse", + error_type: Some("truapi::versioned::payment::HostPaymentTopUpError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 122, + response_id: 123, + }), + }; +} +impl RequestMethod for PaymentTopUp { + type Request = truapi::versioned::payment::HostPaymentTopUpRequest; + type Response = truapi::versioned::payment::HostPaymentTopUpResponse; + type Error = truapi::versioned::payment::HostPaymentTopUpError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `permissions_request_device_permission` method marker. +pub struct PermissionsRequestDevicePermission; +impl PermissionsRequestDevicePermission { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Permissions", + method: "request_device_permission", + wire_name: "permissions_request_device_permission", + request_type: "truapi::versioned::permissions::HostDevicePermissionRequest", + response_type: "truapi::versioned::permissions::HostDevicePermissionResponse", + error_type: Some("truapi::versioned::permissions::HostDevicePermissionError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 8, + response_id: 9, + }), + }; +} +impl RequestMethod for PermissionsRequestDevicePermission { + type Request = truapi::versioned::permissions::HostDevicePermissionRequest; + type Response = truapi::versioned::permissions::HostDevicePermissionResponse; + type Error = truapi::versioned::permissions::HostDevicePermissionError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `permissions_request_remote_permission` method marker. +pub struct PermissionsRequestRemotePermission; +impl PermissionsRequestRemotePermission { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Permissions", + method: "request_remote_permission", + wire_name: "permissions_request_remote_permission", + request_type: "truapi::versioned::permissions::RemotePermissionRequest", + response_type: "truapi::versioned::permissions::RemotePermissionResponse", + error_type: Some("truapi::versioned::permissions::RemotePermissionError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 10, + response_id: 11, + }), + }; +} +impl RequestMethod for PermissionsRequestRemotePermission { + type Request = truapi::versioned::permissions::RemotePermissionRequest; + type Response = truapi::versioned::permissions::RemotePermissionResponse; + type Error = truapi::versioned::permissions::RemotePermissionError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `preimage_lookup_subscribe` method marker. +pub struct PreimageLookupSubscribe; +impl PreimageLookupSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Preimage", + method: "lookup_subscribe", + wire_name: "preimage_lookup_subscribe", + request_type: "truapi::versioned::preimage::RemotePreimageLookupSubscribeRequest", + response_type: "truapi::versioned::preimage::RemotePreimageLookupSubscribeItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 64, + stop_id: 65, + interrupt_id: 66, + receive_id: 67, + }), + }; +} +impl SubscriptionMethod for PreimageLookupSubscribe { + type Request = truapi::versioned::preimage::RemotePreimageLookupSubscribeRequest; + type Item = truapi::versioned::preimage::RemotePreimageLookupSubscribeItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `preimage_submit` method marker. +pub struct PreimageSubmit; +impl PreimageSubmit { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Preimage", + method: "submit", + wire_name: "preimage_submit", + request_type: "truapi::versioned::preimage::RemotePreimageSubmitRequest", + response_type: "truapi::versioned::preimage::RemotePreimageSubmitResponse", + error_type: Some("truapi::versioned::preimage::RemotePreimageSubmitError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 68, + response_id: 69, + }), + }; +} +impl RequestMethod for PreimageSubmit { + type Request = truapi::versioned::preimage::RemotePreimageSubmitRequest; + type Response = truapi::versioned::preimage::RemotePreimageSubmitResponse; + type Error = truapi::versioned::preimage::RemotePreimageSubmitError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `resource_allocation_request` method marker. +pub struct ResourceAllocationRequest; +impl ResourceAllocationRequest { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "ResourceAllocation", + method: "request", + wire_name: "resource_allocation_request", + request_type: "truapi::versioned::resource_allocation::HostRequestResourceAllocationRequest", + response_type: "truapi::versioned::resource_allocation::HostRequestResourceAllocationResponse", + error_type: Some( + "truapi::versioned::resource_allocation::HostRequestResourceAllocationError", + ), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 130, + response_id: 131, + }), + }; +} +impl RequestMethod for ResourceAllocationRequest { + type Request = truapi::versioned::resource_allocation::HostRequestResourceAllocationRequest; + type Response = truapi::versioned::resource_allocation::HostRequestResourceAllocationResponse; + type Error = truapi::versioned::resource_allocation::HostRequestResourceAllocationError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `signing_create_transaction` method marker. +pub struct SigningCreateTransaction; +impl SigningCreateTransaction { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Signing", + method: "create_transaction", + wire_name: "signing_create_transaction", + request_type: "truapi::versioned::signing::HostCreateTransactionRequest", + response_type: "truapi::versioned::signing::HostCreateTransactionResponse", + error_type: Some("truapi::versioned::signing::HostCreateTransactionError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 30, + response_id: 31, + }), + }; +} +impl RequestMethod for SigningCreateTransaction { + type Request = truapi::versioned::signing::HostCreateTransactionRequest; + type Response = truapi::versioned::signing::HostCreateTransactionResponse; + type Error = truapi::versioned::signing::HostCreateTransactionError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `signing_create_transaction_with_legacy_account` method marker. +pub struct SigningCreateTransactionWithLegacyAccount; +impl SigningCreateTransactionWithLegacyAccount { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Signing", + method: "create_transaction_with_legacy_account", + wire_name: "signing_create_transaction_with_legacy_account", + request_type: "truapi::versioned::signing::HostCreateTransactionWithLegacyAccountRequest", + response_type: "truapi::versioned::signing::HostCreateTransactionWithLegacyAccountResponse", + error_type: Some("truapi::versioned::signing::HostCreateTransactionWithLegacyAccountError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 32, + response_id: 33, + }), + }; +} +impl RequestMethod for SigningCreateTransactionWithLegacyAccount { + type Request = truapi::versioned::signing::HostCreateTransactionWithLegacyAccountRequest; + type Response = truapi::versioned::signing::HostCreateTransactionWithLegacyAccountResponse; + type Error = truapi::versioned::signing::HostCreateTransactionWithLegacyAccountError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `signing_sign_raw_with_legacy_account` method marker. +pub struct SigningSignRawWithLegacyAccount; +impl SigningSignRawWithLegacyAccount { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Signing", + method: "sign_raw_with_legacy_account", + wire_name: "signing_sign_raw_with_legacy_account", + request_type: "truapi::versioned::signing::HostSignRawWithLegacyAccountRequest", + response_type: "truapi::versioned::signing::HostSignRawWithLegacyAccountResponse", + error_type: Some("truapi::versioned::signing::HostSignRawWithLegacyAccountError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 34, + response_id: 35, + }), + }; +} +impl RequestMethod for SigningSignRawWithLegacyAccount { + type Request = truapi::versioned::signing::HostSignRawWithLegacyAccountRequest; + type Response = truapi::versioned::signing::HostSignRawWithLegacyAccountResponse; + type Error = truapi::versioned::signing::HostSignRawWithLegacyAccountError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `signing_sign_payload_with_legacy_account` method marker. +pub struct SigningSignPayloadWithLegacyAccount; +impl SigningSignPayloadWithLegacyAccount { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Signing", + method: "sign_payload_with_legacy_account", + wire_name: "signing_sign_payload_with_legacy_account", + request_type: "truapi::versioned::signing::HostSignPayloadWithLegacyAccountRequest", + response_type: "truapi::versioned::signing::HostSignPayloadWithLegacyAccountResponse", + error_type: Some("truapi::versioned::signing::HostSignPayloadWithLegacyAccountError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 36, + response_id: 37, + }), + }; +} +impl RequestMethod for SigningSignPayloadWithLegacyAccount { + type Request = truapi::versioned::signing::HostSignPayloadWithLegacyAccountRequest; + type Response = truapi::versioned::signing::HostSignPayloadWithLegacyAccountResponse; + type Error = truapi::versioned::signing::HostSignPayloadWithLegacyAccountError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `signing_sign_raw` method marker. +pub struct SigningSignRaw; +impl SigningSignRaw { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Signing", + method: "sign_raw", + wire_name: "signing_sign_raw", + request_type: "truapi::versioned::signing::HostSignRawRequest", + response_type: "truapi::versioned::signing::HostSignRawResponse", + error_type: Some("truapi::versioned::signing::HostSignRawError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 114, + response_id: 115, + }), + }; +} +impl RequestMethod for SigningSignRaw { + type Request = truapi::versioned::signing::HostSignRawRequest; + type Response = truapi::versioned::signing::HostSignRawResponse; + type Error = truapi::versioned::signing::HostSignRawError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `signing_sign_payload` method marker. +pub struct SigningSignPayload; +impl SigningSignPayload { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Signing", + method: "sign_payload", + wire_name: "signing_sign_payload", + request_type: "truapi::versioned::signing::HostSignPayloadRequest", + response_type: "truapi::versioned::signing::HostSignPayloadResponse", + error_type: Some("truapi::versioned::signing::HostSignPayloadError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 116, + response_id: 117, + }), + }; +} +impl RequestMethod for SigningSignPayload { + type Request = truapi::versioned::signing::HostSignPayloadRequest; + type Response = truapi::versioned::signing::HostSignPayloadResponse; + type Error = truapi::versioned::signing::HostSignPayloadError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `statement_store_subscribe` method marker. +pub struct StatementStoreSubscribe; +impl StatementStoreSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "StatementStore", + method: "subscribe", + wire_name: "statement_store_subscribe", + request_type: "truapi::versioned::statement_store::RemoteStatementStoreSubscribeRequest", + response_type: "truapi::versioned::statement_store::RemoteStatementStoreSubscribeItem", + error_type: Some("truapi::versioned::statement_store::RemoteStatementStoreSubscribeError"), + kind: MethodKind::ResultSubscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 56, + stop_id: 57, + interrupt_id: 58, + receive_id: 59, + }), + }; +} +impl ResultSubscriptionMethod for StatementStoreSubscribe { + type Request = truapi::versioned::statement_store::RemoteStatementStoreSubscribeRequest; + type Item = truapi::versioned::statement_store::RemoteStatementStoreSubscribeItem; + type Error = truapi::versioned::statement_store::RemoteStatementStoreSubscribeError; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `statement_store_create_proof` method marker. +pub struct StatementStoreCreateProof; +impl StatementStoreCreateProof { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "StatementStore", + method: "create_proof", + wire_name: "statement_store_create_proof", + request_type: "truapi::versioned::statement_store::RemoteStatementStoreCreateProofRequest", + response_type: "truapi::versioned::statement_store::RemoteStatementStoreCreateProofResponse", + error_type: Some( + "truapi::versioned::statement_store::RemoteStatementStoreCreateProofError", + ), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 60, + response_id: 61, + }), + }; +} +impl RequestMethod for StatementStoreCreateProof { + type Request = truapi::versioned::statement_store::RemoteStatementStoreCreateProofRequest; + type Response = truapi::versioned::statement_store::RemoteStatementStoreCreateProofResponse; + type Error = truapi::versioned::statement_store::RemoteStatementStoreCreateProofError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `statement_store_create_proof_authorized` method marker. +pub struct StatementStoreCreateProofAuthorized; +impl StatementStoreCreateProofAuthorized { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "StatementStore", + method: "create_proof_authorized", + wire_name: "statement_store_create_proof_authorized", + request_type: "truapi::versioned::statement_store::RemoteStatementStoreCreateProofAuthorizedRequest", + response_type: "truapi::versioned::statement_store::RemoteStatementStoreCreateProofAuthorizedResponse", + error_type: Some( + "truapi::versioned::statement_store::RemoteStatementStoreCreateProofAuthorizedError", + ), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 132, + response_id: 133, + }), + }; +} +impl RequestMethod for StatementStoreCreateProofAuthorized { + type Request = + truapi::versioned::statement_store::RemoteStatementStoreCreateProofAuthorizedRequest; + type Response = + truapi::versioned::statement_store::RemoteStatementStoreCreateProofAuthorizedResponse; + type Error = truapi::versioned::statement_store::RemoteStatementStoreCreateProofAuthorizedError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `statement_store_submit` method marker. +pub struct StatementStoreSubmit; +impl StatementStoreSubmit { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "StatementStore", + method: "submit", + wire_name: "statement_store_submit", + request_type: "truapi::versioned::statement_store::RemoteStatementStoreSubmitRequest", + response_type: "()", + error_type: Some("truapi::versioned::statement_store::RemoteStatementStoreSubmitError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: true, + wire: MethodWire::Request(RequestFrameIds { + request_id: 62, + response_id: 63, + }), + }; +} +impl RequestMethod for StatementStoreSubmit { + type Request = truapi::versioned::statement_store::RemoteStatementStoreSubmitRequest; + type Response = (); + type Error = truapi::versioned::statement_store::RemoteStatementStoreSubmitError; + const RESPONSE_VERSIONED: bool = false; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `system_handshake` method marker. +pub struct SystemHandshake; +impl SystemHandshake { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "System", + method: "handshake", + wire_name: "system_handshake", + request_type: "truapi::versioned::system::HostHandshakeRequest", + response_type: "truapi::versioned::system::HostHandshakeResponse", + error_type: Some("truapi::versioned::system::HostHandshakeError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 0, + response_id: 1, + }), + }; +} +impl RequestMethod for SystemHandshake { + type Request = truapi::versioned::system::HostHandshakeRequest; + type Response = truapi::versioned::system::HostHandshakeResponse; + type Error = truapi::versioned::system::HostHandshakeError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `system_feature_supported` method marker. +pub struct SystemFeatureSupported; +impl SystemFeatureSupported { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "System", + method: "feature_supported", + wire_name: "system_feature_supported", + request_type: "truapi::versioned::system::HostFeatureSupportedRequest", + response_type: "truapi::versioned::system::HostFeatureSupportedResponse", + error_type: Some("truapi::versioned::system::HostFeatureSupportedError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 2, + response_id: 3, + }), + }; +} +impl RequestMethod for SystemFeatureSupported { + type Request = truapi::versioned::system::HostFeatureSupportedRequest; + type Response = truapi::versioned::system::HostFeatureSupportedResponse; + type Error = truapi::versioned::system::HostFeatureSupportedError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `system_navigate_to` method marker. +pub struct SystemNavigateTo; +impl SystemNavigateTo { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "System", + method: "navigate_to", + wire_name: "system_navigate_to", + request_type: "truapi::versioned::system::HostNavigateToRequest", + response_type: "truapi::versioned::system::HostNavigateToResponse", + error_type: Some("truapi::versioned::system::HostNavigateToError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 6, + response_id: 7, + }), + }; +} +impl RequestMethod for SystemNavigateTo { + type Request = truapi::versioned::system::HostNavigateToRequest; + type Response = truapi::versioned::system::HostNavigateToResponse; + type Error = truapi::versioned::system::HostNavigateToError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `system_host_info` method marker. +pub struct SystemHostInfo; +impl SystemHostInfo { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "System", + method: "host_info", + wire_name: "system_host_info", + request_type: "truapi::versioned::system::HostInfoRequest", + response_type: "truapi::versioned::system::HostInfoResponse", + error_type: Some("truapi::versioned::system::HostInfoError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 192, + response_id: 193, + }), + }; +} +impl RequestMethod for SystemHostInfo { + type Request = truapi::versioned::system::HostInfoRequest; + type Response = truapi::versioned::system::HostInfoResponse; + type Error = truapi::versioned::system::HostInfoError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `system_get_product_context` method marker. +pub struct SystemGetProductContext; +impl SystemGetProductContext { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "System", + method: "get_product_context", + wire_name: "system_get_product_context", + request_type: "truapi::versioned::system::HostGetProductContextRequest", + response_type: "truapi::versioned::system::HostGetProductContextResponse", + error_type: Some("truapi::versioned::system::HostGetProductContextError"), + kind: MethodKind::Request, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Request(RequestFrameIds { + request_id: 190, + response_id: 191, + }), + }; +} +impl RequestMethod for SystemGetProductContext { + type Request = truapi::versioned::system::HostGetProductContextRequest; + type Response = truapi::versioned::system::HostGetProductContextResponse; + type Error = truapi::versioned::system::HostGetProductContextError; + const RESPONSE_VERSIONED: bool = true; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// `theme_subscribe` method marker. +pub struct ThemeSubscribe; +impl ThemeSubscribe { + /// Canonical metadata and frame ids for this method. + pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor { + service: "Theme", + method: "subscribe", + wire_name: "theme_subscribe", + request_type: "()", + response_type: "truapi::versioned::theme::HostThemeSubscribeItem", + error_type: None, + kind: MethodKind::Subscription, + direction: Direction::ProductToHost, + required_execution: None, + sensitive: false, + wire: MethodWire::Subscription(SubscriptionFrameIds { + start_id: 104, + stop_id: 105, + interrupt_id: 106, + receive_id: 107, + }), + }; +} +impl SubscriptionMethod for ThemeSubscribe { + type Request = (); + type Item = truapi::versioned::theme::HostThemeSubscribeItem; + const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR; +} + +/// Generated `APP_METHODS` execution catalog. +pub const APP_METHODS: &[MethodDescriptor] = &[ + AccountConnectionStatusSubscribe::DESCRIPTOR, + AccountGetAccount::DESCRIPTOR, + AccountGetAccountAlias::DESCRIPTOR, + AccountCreateAccountProof::DESCRIPTOR, + AccountSignVrf::DESCRIPTOR, + AccountRegisterRingVrfKey::DESCRIPTOR, + AccountListRingVrfKeys::DESCRIPTOR, + AccountRingVrfSign::DESCRIPTOR, + AccountGetLegacyAccounts::DESCRIPTOR, + AccountGetUserId::DESCRIPTOR, + AccountRequestLogin::DESCRIPTOR, + ChainFollowHeadSubscribe::DESCRIPTOR, + ChainGetHeadHeader::DESCRIPTOR, + ChainGetHeadBody::DESCRIPTOR, + ChainGetHeadStorage::DESCRIPTOR, + ChainCallHead::DESCRIPTOR, + ChainUnpinHead::DESCRIPTOR, + ChainContinueHead::DESCRIPTOR, + ChainStopHeadOperation::DESCRIPTOR, + ChainGetSpecGenesisHash::DESCRIPTOR, + ChainGetSpecChainName::DESCRIPTOR, + ChainGetSpecProperties::DESCRIPTOR, + ChainBroadcastTransaction::DESCRIPTOR, + ChainStopTransaction::DESCRIPTOR, + ChainGetChainInfo::DESCRIPTOR, + CoinPaymentCreatePurse::DESCRIPTOR, + CoinPaymentQueryPurse::DESCRIPTOR, + CoinPaymentRebalancePurse::DESCRIPTOR, + CoinPaymentDeletePurse::DESCRIPTOR, + CoinPaymentCreateReceivable::DESCRIPTOR, + CoinPaymentCreateCheque::DESCRIPTOR, + CoinPaymentDeposit::DESCRIPTOR, + CoinPaymentRefund::DESCRIPTOR, + CoinPaymentListenForPayment::DESCRIPTOR, + EntropyDerive::DESCRIPTOR, + LocalStorageRead::DESCRIPTOR, + LocalStorageWrite::DESCRIPTOR, + LocalStorageClear::DESCRIPTOR, + LocaleSubscribe::DESCRIPTOR, + NotificationsSendPushNotification::DESCRIPTOR, + NotificationsCancelPushNotification::DESCRIPTOR, + PaymentBalanceSubscribe::DESCRIPTOR, + PaymentRequest::DESCRIPTOR, + PaymentStatusSubscribe::DESCRIPTOR, + PaymentTopUp::DESCRIPTOR, + PermissionsRequestDevicePermission::DESCRIPTOR, + PermissionsRequestRemotePermission::DESCRIPTOR, + PreimageLookupSubscribe::DESCRIPTOR, + PreimageSubmit::DESCRIPTOR, + ResourceAllocationRequest::DESCRIPTOR, + SigningCreateTransaction::DESCRIPTOR, + SigningCreateTransactionWithLegacyAccount::DESCRIPTOR, + SigningSignRawWithLegacyAccount::DESCRIPTOR, + SigningSignPayloadWithLegacyAccount::DESCRIPTOR, + SigningSignRaw::DESCRIPTOR, + SigningSignPayload::DESCRIPTOR, + StatementStoreSubscribe::DESCRIPTOR, + StatementStoreCreateProof::DESCRIPTOR, + StatementStoreCreateProofAuthorized::DESCRIPTOR, + StatementStoreSubmit::DESCRIPTOR, + SystemHandshake::DESCRIPTOR, + SystemFeatureSupported::DESCRIPTOR, + SystemNavigateTo::DESCRIPTOR, + SystemHostInfo::DESCRIPTOR, + SystemGetProductContext::DESCRIPTOR, + ThemeSubscribe::DESCRIPTOR, +]; + +/// Generated `WIDGET_METHODS` execution catalog. +pub const WIDGET_METHODS: &[MethodDescriptor] = &[ + AccountConnectionStatusSubscribe::DESCRIPTOR, + AccountGetAccount::DESCRIPTOR, + AccountGetAccountAlias::DESCRIPTOR, + AccountCreateAccountProof::DESCRIPTOR, + AccountSignVrf::DESCRIPTOR, + AccountRegisterRingVrfKey::DESCRIPTOR, + AccountListRingVrfKeys::DESCRIPTOR, + AccountRingVrfSign::DESCRIPTOR, + AccountGetLegacyAccounts::DESCRIPTOR, + AccountGetUserId::DESCRIPTOR, + AccountRequestLogin::DESCRIPTOR, + ChainFollowHeadSubscribe::DESCRIPTOR, + ChainGetHeadHeader::DESCRIPTOR, + ChainGetHeadBody::DESCRIPTOR, + ChainGetHeadStorage::DESCRIPTOR, + ChainCallHead::DESCRIPTOR, + ChainUnpinHead::DESCRIPTOR, + ChainContinueHead::DESCRIPTOR, + ChainStopHeadOperation::DESCRIPTOR, + ChainGetSpecGenesisHash::DESCRIPTOR, + ChainGetSpecChainName::DESCRIPTOR, + ChainGetSpecProperties::DESCRIPTOR, + ChainBroadcastTransaction::DESCRIPTOR, + ChainStopTransaction::DESCRIPTOR, + ChainGetChainInfo::DESCRIPTOR, + CoinPaymentCreatePurse::DESCRIPTOR, + CoinPaymentQueryPurse::DESCRIPTOR, + CoinPaymentRebalancePurse::DESCRIPTOR, + CoinPaymentDeletePurse::DESCRIPTOR, + CoinPaymentCreateReceivable::DESCRIPTOR, + CoinPaymentCreateCheque::DESCRIPTOR, + CoinPaymentDeposit::DESCRIPTOR, + CoinPaymentRefund::DESCRIPTOR, + CoinPaymentListenForPayment::DESCRIPTOR, + EntropyDerive::DESCRIPTOR, + LocalStorageRead::DESCRIPTOR, + LocalStorageWrite::DESCRIPTOR, + LocalStorageClear::DESCRIPTOR, + LocaleSubscribe::DESCRIPTOR, + NotificationsSendPushNotification::DESCRIPTOR, + NotificationsCancelPushNotification::DESCRIPTOR, + PaymentBalanceSubscribe::DESCRIPTOR, + PaymentRequest::DESCRIPTOR, + PaymentStatusSubscribe::DESCRIPTOR, + PaymentTopUp::DESCRIPTOR, + PermissionsRequestDevicePermission::DESCRIPTOR, + PermissionsRequestRemotePermission::DESCRIPTOR, + PreimageLookupSubscribe::DESCRIPTOR, + PreimageSubmit::DESCRIPTOR, + ResourceAllocationRequest::DESCRIPTOR, + SigningCreateTransaction::DESCRIPTOR, + SigningCreateTransactionWithLegacyAccount::DESCRIPTOR, + SigningSignRawWithLegacyAccount::DESCRIPTOR, + SigningSignPayloadWithLegacyAccount::DESCRIPTOR, + SigningSignRaw::DESCRIPTOR, + SigningSignPayload::DESCRIPTOR, + StatementStoreSubscribe::DESCRIPTOR, + StatementStoreCreateProof::DESCRIPTOR, + StatementStoreCreateProofAuthorized::DESCRIPTOR, + StatementStoreSubmit::DESCRIPTOR, + SystemHandshake::DESCRIPTOR, + SystemFeatureSupported::DESCRIPTOR, + SystemNavigateTo::DESCRIPTOR, + SystemHostInfo::DESCRIPTOR, + SystemGetProductContext::DESCRIPTOR, + ThemeSubscribe::DESCRIPTOR, +]; + +/// Generated `WORKER_METHODS` execution catalog. +pub const WORKER_METHODS: &[MethodDescriptor] = &[ + AccountConnectionStatusSubscribe::DESCRIPTOR, + AccountGetAccount::DESCRIPTOR, + AccountGetAccountAlias::DESCRIPTOR, + AccountCreateAccountProof::DESCRIPTOR, + AccountSignVrf::DESCRIPTOR, + AccountRegisterRingVrfKey::DESCRIPTOR, + AccountListRingVrfKeys::DESCRIPTOR, + AccountRingVrfSign::DESCRIPTOR, + AccountGetLegacyAccounts::DESCRIPTOR, + AccountGetUserId::DESCRIPTOR, + AccountRequestLogin::DESCRIPTOR, + ChainFollowHeadSubscribe::DESCRIPTOR, + ChainGetHeadHeader::DESCRIPTOR, + ChainGetHeadBody::DESCRIPTOR, + ChainGetHeadStorage::DESCRIPTOR, + ChainCallHead::DESCRIPTOR, + ChainUnpinHead::DESCRIPTOR, + ChainContinueHead::DESCRIPTOR, + ChainStopHeadOperation::DESCRIPTOR, + ChainGetSpecGenesisHash::DESCRIPTOR, + ChainGetSpecChainName::DESCRIPTOR, + ChainGetSpecProperties::DESCRIPTOR, + ChainBroadcastTransaction::DESCRIPTOR, + ChainStopTransaction::DESCRIPTOR, + ChainGetChainInfo::DESCRIPTOR, + ChatCreateRoom::DESCRIPTOR, + ChatRegisterBot::DESCRIPTOR, + ChatListSubscribe::DESCRIPTOR, + ChatPostMessage::DESCRIPTOR, + ChatActionSubscribe::DESCRIPTOR, + ChatCustomMessageRender::DESCRIPTOR, + CoinPaymentCreatePurse::DESCRIPTOR, + CoinPaymentQueryPurse::DESCRIPTOR, + CoinPaymentRebalancePurse::DESCRIPTOR, + CoinPaymentDeletePurse::DESCRIPTOR, + CoinPaymentCreateReceivable::DESCRIPTOR, + CoinPaymentCreateCheque::DESCRIPTOR, + CoinPaymentDeposit::DESCRIPTOR, + CoinPaymentRefund::DESCRIPTOR, + CoinPaymentListenForPayment::DESCRIPTOR, + EntropyDerive::DESCRIPTOR, + LocalStorageRead::DESCRIPTOR, + LocalStorageWrite::DESCRIPTOR, + LocalStorageClear::DESCRIPTOR, + LocaleSubscribe::DESCRIPTOR, + NotificationsSendPushNotification::DESCRIPTOR, + NotificationsCancelPushNotification::DESCRIPTOR, + PaymentBalanceSubscribe::DESCRIPTOR, + PaymentRequest::DESCRIPTOR, + PaymentStatusSubscribe::DESCRIPTOR, + PaymentTopUp::DESCRIPTOR, + PermissionsRequestDevicePermission::DESCRIPTOR, + PermissionsRequestRemotePermission::DESCRIPTOR, + PreimageLookupSubscribe::DESCRIPTOR, + PreimageSubmit::DESCRIPTOR, + ResourceAllocationRequest::DESCRIPTOR, + SigningCreateTransaction::DESCRIPTOR, + SigningCreateTransactionWithLegacyAccount::DESCRIPTOR, + SigningSignRawWithLegacyAccount::DESCRIPTOR, + SigningSignPayloadWithLegacyAccount::DESCRIPTOR, + SigningSignRaw::DESCRIPTOR, + SigningSignPayload::DESCRIPTOR, + StatementStoreSubscribe::DESCRIPTOR, + StatementStoreCreateProof::DESCRIPTOR, + StatementStoreCreateProofAuthorized::DESCRIPTOR, + StatementStoreSubmit::DESCRIPTOR, + SystemHandshake::DESCRIPTOR, + SystemFeatureSupported::DESCRIPTOR, + SystemNavigateTo::DESCRIPTOR, + SystemHostInfo::DESCRIPTOR, + SystemGetProductContext::DESCRIPTOR, + ThemeSubscribe::DESCRIPTOR, +]; + +/// Generated `WORKER_ONLY_METHODS` execution catalog. +pub const WORKER_ONLY_METHODS: &[MethodDescriptor] = &[ + ChatCreateRoom::DESCRIPTOR, + ChatRegisterBot::DESCRIPTOR, + ChatListSubscribe::DESCRIPTOR, + ChatPostMessage::DESCRIPTOR, + ChatActionSubscribe::DESCRIPTOR, + ChatCustomMessageRender::DESCRIPTOR, +]; diff --git a/rust/crates/truapi-client/src/lib.rs b/rust/crates/truapi-client/src/lib.rs new file mode 100644 index 000000000..f40b6e57a --- /dev/null +++ b/rust/crates/truapi-client/src/lib.rs @@ -0,0 +1,556 @@ +#![no_std] + +//! Transport-neutral TrUAPI client codecs and generated method catalog. +//! +//! The crate owns no executor or transport. A product runtime sends the encoded +//! frames through its native transport, then decodes returned frames with the +//! same generated method marker. + +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; +use parity_scale_codec::{Decode, Encode, Error as CodecError, Input}; +use truapi::CallError; + +mod generated; +pub use generated::*; + +/// Product executable kinds used by TrUAPI authorization. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ExecutionKind { + /// Full application surface. + App, + /// Embedded widget surface. + Widget, + /// Background product worker. + Worker, +} + +/// Direction in which a method's initial frame travels. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Direction { + /// Product starts the call and the host serves it. + ProductToHost, + /// Host starts the call and the product serves it. + HostToProduct, +} + +/// Wire interaction shape. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MethodKind { + /// One request followed by one response. + Request, + /// Start/receive stream with no typed start failure. + Subscription, + /// Start/receive stream with a typed start failure. + ResultSubscription, +} + +/// Request/response discriminants. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct RequestFrameIds { + /// Request frame discriminant. + pub request_id: u8, + /// Response frame discriminant. + pub response_id: u8, +} + +/// Subscription discriminants. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct SubscriptionFrameIds { + /// Subscription start discriminant. + pub start_id: u8, + /// Subscription stop discriminant. + pub stop_id: u8, + /// Server-side interruption discriminant. + pub interrupt_id: u8, + /// Subscription item discriminant. + pub receive_id: u8, +} + +/// Wire ids for one method. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MethodWire { + /// Request/response pair. + Request(RequestFrameIds), + /// Subscription quartet. + Subscription(SubscriptionFrameIds), +} + +/// Generated metadata for one canonical method. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct MethodDescriptor { + /// Canonical service trait name. + pub service: &'static str, + /// Rust method name. + pub method: &'static str, + /// Globally unique wire method name. + pub wire_name: &'static str, + /// Rust type of the versioned request envelope. + pub request_type: &'static str, + /// Rust type of the versioned success or stream-item envelope. + pub response_type: &'static str, + /// Rust type of the versioned domain-error envelope, when the method has one. + pub error_type: Option<&'static str>, + /// Interaction shape. + pub kind: MethodKind, + /// Initial-frame direction. + pub direction: Direction, + /// Required executable kind, or `None` when every kind may call it. + pub required_execution: Option, + /// Whether diagnostics must redact this method's payload. + pub sensitive: bool, + /// Canonical frame discriminants. + pub wire: MethodWire, +} + +/// Generated marker for a product-initiated request method. +pub trait RequestMethod { + /// Versioned request envelope. + type Request: Encode; + /// Versioned success envelope. + type Response: Decode; + /// Versioned domain-error envelope. + type Error: Decode; + /// Whether the success value is a versioned wrapper reconstructed from the outer version byte. + const RESPONSE_VERSIONED: bool; + /// Canonical method metadata. + const DESCRIPTOR: MethodDescriptor; +} + +/// Generated marker for a product-initiated subscription. +pub trait SubscriptionMethod { + /// Versioned start request, or unit for an empty payload. + type Request: Encode; + /// Versioned stream item. + type Item: Decode; + /// Canonical method metadata. + const DESCRIPTOR: MethodDescriptor; +} + +/// Generated marker for a product-initiated subscription with typed start errors. +pub trait ResultSubscriptionMethod { + /// Versioned start request. + type Request: Encode; + /// Versioned stream item. + type Item: Decode; + /// Versioned domain-error envelope. + type Error: Decode; + /// Canonical method metadata. + const DESCRIPTOR: MethodDescriptor; +} + +/// Generated marker for a host-initiated subscription served by a product. +pub trait HostSubscriptionMethod { + /// Versioned host request. + type Request: Decode; + /// Versioned product stream item. + type Item: Encode; + /// Canonical method metadata. + const DESCRIPTOR: MethodDescriptor; +} + +/// Decoded frame value paired with its transport request id. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Decoded { + /// Request id from the frame envelope. + pub request_id: String, + /// Decoded typed payload. + pub value: T, +} + +/// Typed domain outcome carried by a product-initiated request response. +pub type RequestOutcome = + Result<::Response, CallError<::Error>>; + +/// Result of decoding one product-initiated request response frame. +pub type DecodedResponse = Result>, DecodeError>; + +/// Structural failure while decoding a TrUAPI frame. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DecodeError { + /// The frame or payload is not valid SCALE for the expected type. + Malformed, + /// The payload contains bytes after the expected value. + TrailingBytes, + /// The frame carries a discriminant other than the method leg expected. + UnexpectedDiscriminant { + /// Expected wire discriminant. + expected: u8, + /// Actual wire discriminant. + actual: u8, + }, + /// A versioned response contains neither the success nor failure tag. + UnexpectedResultDiscriminant(u8), + /// The generated descriptor has a wire shape incompatible with the operation. + WrongMethodKind, +} + +/// Encodes a product-initiated request frame without an intermediate payload allocation. +pub fn encode_request(request_id: &str, request: &M::Request) -> Vec { + let ids = generated_request_ids(M::DESCRIPTOR); + encode_value_frame(request_id, ids.request_id, request) +} + +/// Decodes a product-initiated request's response frame. +pub fn decode_response(frame: &[u8]) -> DecodedResponse { + let ids = generated_request_ids(M::DESCRIPTOR); + let frame = decode_frame(frame)?; + expect_discriminant(ids.response_id, frame.discriminant)?; + let payload = frame.payload; + if payload.len() < 2 { + return Err(DecodeError::Malformed); + } + let version = payload[0]; + let value = match payload[1] { + 0 if M::RESPONSE_VERSIONED => Ok(decode_prefixed_exact(version, &payload[2..])?), + 0 => Ok(decode_exact(&payload[2..])?), + 1 => Err(decode_exact(&payload[2..])?), + other => return Err(DecodeError::UnexpectedResultDiscriminant(other)), + }; + Ok(Decoded { + request_id: frame.request_id, + value, + }) +} + +/// Encodes a product-initiated subscription start frame. +pub fn encode_subscription_start( + request_id: &str, + request: &M::Request, +) -> Vec { + let ids = generated_subscription_ids(M::DESCRIPTOR); + encode_value_frame(request_id, ids.start_id, request) +} + +/// Encodes a product-initiated result-subscription start frame. +pub fn encode_result_subscription_start( + request_id: &str, + request: &M::Request, +) -> Vec { + let ids = generated_subscription_ids(M::DESCRIPTOR); + encode_value_frame(request_id, ids.start_id, request) +} + +/// Encodes a stop frame for a product-initiated subscription. +/// +/// Returns [`DecodeError::WrongMethodKind`] when `descriptor` describes a request. +pub fn encode_subscription_stop( + request_id: &str, + descriptor: MethodDescriptor, +) -> Result, DecodeError> { + let ids = subscription_ids(descriptor)?; + Ok(encode_empty_frame(request_id, ids.stop_id)) +} + +/// Decodes a regular subscription item frame. +pub fn decode_subscription_item( + frame: &[u8], +) -> Result, DecodeError> { + decode_stream_item::(frame, generated_subscription_ids(M::DESCRIPTOR).receive_id) +} + +/// Decodes a result-subscription item frame. +pub fn decode_result_subscription_item( + frame: &[u8], +) -> Result, DecodeError> { + decode_stream_item::(frame, generated_subscription_ids(M::DESCRIPTOR).receive_id) +} + +/// Decodes a typed result-subscription interruption. +pub fn decode_result_subscription_interrupt( + frame: &[u8], +) -> Result>, DecodeError> { + let ids = generated_subscription_ids(M::DESCRIPTOR); + let frame = decode_frame(frame)?; + expect_discriminant(ids.interrupt_id, frame.discriminant)?; + let (_, payload) = frame.payload.split_first().ok_or(DecodeError::Malformed)?; + Ok(Decoded { + request_id: frame.request_id, + value: decode_exact(payload)?, + }) +} + +/// Returns whether a frame is the interruption leg for a subscription descriptor. +/// +/// Returns [`DecodeError::WrongMethodKind`] when `descriptor` describes a request. +pub fn is_subscription_interrupt( + frame: &[u8], + descriptor: MethodDescriptor, +) -> Result { + let ids = subscription_ids(descriptor)?; + Ok(decode_frame(frame)?.discriminant == ids.interrupt_id) +} + +/// Decodes a host-initiated subscription start for a product worker. +pub fn decode_host_subscription_start( + frame: &[u8], +) -> Result, DecodeError> { + let ids = generated_subscription_ids(M::DESCRIPTOR); + let frame = decode_frame(frame)?; + expect_discriminant(ids.start_id, frame.discriminant)?; + Ok(Decoded { + request_id: frame.request_id, + value: decode_exact(frame.payload)?, + }) +} + +/// Encodes one product-served item for a host-initiated subscription. +pub fn encode_host_subscription_item( + request_id: &str, + item: &M::Item, +) -> Vec { + let ids = generated_subscription_ids(M::DESCRIPTOR); + encode_value_frame(request_id, ids.receive_id, item) +} + +/// Encodes product-side termination of a host-initiated subscription. +pub fn encode_host_subscription_interrupt(request_id: &str) -> Vec { + let ids = generated_subscription_ids(M::DESCRIPTOR); + encode_empty_frame(request_id, ids.interrupt_id) +} + +/// Returns whether a host frame stops a product-served subscription. +pub fn is_host_subscription_stop( + frame: &[u8], +) -> Result { + let ids = generated_subscription_ids(M::DESCRIPTOR); + Ok(decode_frame(frame)?.discriminant == ids.stop_id) +} + +fn request_ids(descriptor: MethodDescriptor) -> Result { + match descriptor.wire { + MethodWire::Request(ids) => Ok(ids), + MethodWire::Subscription(_) => Err(DecodeError::WrongMethodKind), + } +} + +fn subscription_ids(descriptor: MethodDescriptor) -> Result { + match descriptor.wire { + MethodWire::Subscription(ids) => Ok(ids), + MethodWire::Request(_) => Err(DecodeError::WrongMethodKind), + } +} + +fn generated_request_ids(descriptor: MethodDescriptor) -> RequestFrameIds { + request_ids(descriptor).expect("generated request descriptor must use request wire ids") +} + +fn generated_subscription_ids(descriptor: MethodDescriptor) -> SubscriptionFrameIds { + subscription_ids(descriptor) + .expect("generated subscription descriptor must use subscription wire ids") +} + +fn encode_value_frame( + request_id: &str, + discriminant: u8, + value: &T, +) -> Vec { + let mut frame = Vec::new(); + request_id.encode_to(&mut frame); + frame.push(discriminant); + value.encode_to(&mut frame); + frame +} + +fn encode_empty_frame(request_id: &str, discriminant: u8) -> Vec { + let mut frame = Vec::new(); + request_id.encode_to(&mut frame); + frame.push(discriminant); + frame +} + +struct BorrowedFrame<'a> { + request_id: String, + discriminant: u8, + payload: &'a [u8], +} + +fn decode_frame(mut frame: &[u8]) -> Result, DecodeError> { + let request_id = String::decode(&mut frame).map_err(|_| DecodeError::Malformed)?; + let (&discriminant, payload) = frame.split_first().ok_or(DecodeError::Malformed)?; + Ok(BorrowedFrame { + request_id, + discriminant, + payload, + }) +} + +fn expect_discriminant(expected: u8, actual: u8) -> Result<(), DecodeError> { + if actual == expected { + Ok(()) + } else { + Err(DecodeError::UnexpectedDiscriminant { expected, actual }) + } +} + +fn decode_stream_item(frame: &[u8], receive_id: u8) -> Result, DecodeError> { + let frame = decode_frame(frame)?; + expect_discriminant(receive_id, frame.discriminant)?; + Ok(Decoded { + request_id: frame.request_id, + value: decode_exact(frame.payload)?, + }) +} + +fn decode_exact(mut payload: &[u8]) -> Result { + let value = T::decode(&mut payload).map_err(|_| DecodeError::Malformed)?; + if payload.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytes) + } +} + +fn decode_prefixed_exact(prefix: u8, payload: &[u8]) -> Result { + let mut input = PrefixedInput { + prefix: Some(prefix), + payload, + }; + let value = T::decode(&mut input).map_err(|_| DecodeError::Malformed)?; + match input.remaining_len().map_err(|_| DecodeError::Malformed)? { + Some(0) => Ok(value), + _ => Err(DecodeError::TrailingBytes), + } +} + +struct PrefixedInput<'a> { + prefix: Option, + payload: &'a [u8], +} + +impl Input for PrefixedInput<'_> { + fn remaining_len(&mut self) -> Result, CodecError> { + Ok(Some( + usize::from(self.prefix.is_some()) + self.payload.len(), + )) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), CodecError> { + let mut written = 0; + if let Some(prefix) = self.prefix.take() { + let Some(first) = into.first_mut() else { + self.prefix = Some(prefix); + return Ok(()); + }; + *first = prefix; + written = 1; + } + let remaining = &mut into[written..]; + if remaining.len() > self.payload.len() { + return Err("not enough data to fill buffer".into()); + } + remaining.copy_from_slice(&self.payload[..remaining.len()]); + self.payload = &self.payload[remaining.len()..]; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::vec; + use parity_scale_codec::Encode; + use truapi::v01; + use truapi::versioned::system::{HostHandshakeRequest, HostHandshakeResponse}; + + #[test] + fn catalogs_partition_worker_only_chat() { + assert_eq!(APP_METHODS.len(), 66); + assert_eq!(WIDGET_METHODS.len(), 66); + assert_eq!(WORKER_METHODS.len(), 72); + assert_eq!(WORKER_ONLY_METHODS.len(), 6); + assert!(WORKER_ONLY_METHODS.iter().all(|method| { + method.service == "Chat" && method.required_execution == Some(ExecutionKind::Worker) + })); + } + + #[test] + fn request_and_response_use_canonical_envelopes() { + let request = HostHandshakeRequest::V1(v01::HostHandshakeRequest { codec_version: 1 }); + assert_eq!( + encode_request::("p:1", &request), + [12, b'p', b':', b'1', 0, 0, 1] + ); + + let decoded = decode_response::(&[12, b'p', b':', b'1', 1, 0, 0]) + .expect("response frame"); + assert_eq!(decoded.request_id, "p:1"); + assert_eq!(decoded.value, Ok(HostHandshakeResponse::V1)); + } + + #[test] + fn response_domain_error_preserves_versioned_payload() { + let error = CallError::Domain(truapi::versioned::system::HostHandshakeError::V1( + v01::HostHandshakeError::UnsupportedProtocolVersion, + )); + let mut frame = vec![12, b'p', b':', b'1', 1, 0, 1]; + error.encode_to(&mut frame); + let decoded = decode_response::(&frame).expect("error frame"); + assert_eq!(decoded.value, Err(error)); + } + + #[test] + fn worker_serves_host_initiated_custom_chat_rendering() { + let request = truapi::versioned::chat::ProductChatCustomMessageRenderRequest::V1( + v01::ProductChatCustomMessageRenderRequest { + message_id: "message-7".into(), + message_type: "poll".into(), + payload: vec![1, 2, 3], + }, + ); + let ids = generated_subscription_ids(ChatCustomMessageRender::DESCRIPTOR); + let start = encode_value_frame("host:4", ids.start_id, &request); + let decoded = + decode_host_subscription_start::(&start).expect("start frame"); + assert_eq!(decoded.request_id, "host:4"); + assert_eq!(decoded.value, request); + + let item = truapi::versioned::chat::ProductChatCustomMessageRenderItem::V1( + v01::CustomRendererNode::Nil, + ); + let rendered = encode_host_subscription_item::("host:4", &item); + let rendered = decode_frame(&rendered).expect("rendered item frame"); + assert_eq!(rendered.discriminant, ids.receive_id); + assert_eq!( + decode_exact::( + rendered.payload + ), + Ok(item) + ); + + let stop = encode_empty_frame("host:4", ids.stop_id); + assert_eq!( + is_host_subscription_stop::(&stop), + Ok(true) + ); + let interrupt = encode_host_subscription_interrupt::("host:4"); + assert_eq!( + decode_frame(&interrupt) + .expect("interrupt frame") + .discriminant, + ids.interrupt_id + ); + } + + #[test] + fn descriptor_apis_validate_subscription_wire_ids() { + let descriptor = AccountConnectionStatusSubscribe::DESCRIPTOR; + let expected_ids = generated_subscription_ids(descriptor); + let stop = encode_subscription_stop("p:1", descriptor).expect("subscription descriptor"); + assert_eq!( + decode_frame(&stop).expect("stop frame").discriminant, + expected_ids.stop_id + ); + + assert_eq!( + encode_subscription_stop("p:1", SystemHandshake::DESCRIPTOR), + Err(DecodeError::WrongMethodKind) + ); + assert_eq!( + is_subscription_interrupt(&stop, SystemHandshake::DESCRIPTOR), + Err(DecodeError::WrongMethodKind) + ); + } +} diff --git a/rust/crates/truapi-codegen/src/main.rs b/rust/crates/truapi-codegen/src/main.rs index 032982d55..ea4cfb752 100644 --- a/rust/crates/truapi-codegen/src/main.rs +++ b/rust/crates/truapi-codegen/src/main.rs @@ -59,6 +59,10 @@ struct Cli { #[arg(long)] rust_output: Option, + /// Output file for the generated no-std Rust client catalog (optional). + #[arg(long)] + rust_client_output: Option, + /// Path to rustdoc JSON for the `truapi-platform` crate (optional). /// /// When provided together with `--platform-ts-output`, walks the @@ -165,6 +169,20 @@ fn main() -> Result<()> { .with_context(|| format!("writing Rust dispatcher to {}", path.display()))?; println!("Wrote Rust dispatcher to {}", path.display()); } + if let Some(path) = &cli.rust_client_output { + let schema_hash = + ts::wire_schema_hash(&api, ts::latest_wire_version(&api), cli.codec_version) + .context("computing Rust client wire schema hash")?; + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent) + .with_context(|| format!("creating {}", parent.display()))?; + } + let client = rust::generate_client(&api, &schema_hash) + .context("generating no-std Rust client catalog")?; + std::fs::write(path, client) + .with_context(|| format!("writing Rust client catalog to {}", path.display()))?; + println!("Wrote Rust client catalog to {}", path.display()); + } if let Some(input) = &cli.platform_input { if cli.platform_wasm_adapter_output.is_some() && cli.platform_ts_output.is_none() { anyhow::bail!("--platform-wasm-adapter-output requires --platform-ts-output"); diff --git a/rust/crates/truapi-codegen/src/rust.rs b/rust/crates/truapi-codegen/src/rust.rs index 13bddf961..dfc93d8ce 100644 --- a/rust/crates/truapi-codegen/src/rust.rs +++ b/rust/crates/truapi-codegen/src/rust.rs @@ -14,10 +14,12 @@ use convert_case::{Case, Casing}; use crate::platform::PlatformDefinition; use crate::rustdoc::*; +mod client; mod dispatcher; mod wasm_bridge; mod wire_table; +pub use client::generate_client; pub use dispatcher::generate_dispatcher; pub use wasm_bridge::generate_wasm_bridge; pub use wire_table::generate_wire_table; @@ -217,6 +219,50 @@ mod tests { .collect() } + #[test] + fn test_client_catalog_rejects_request_id_overflow() { + let api = ApiDefinition { + traits: vec![TraitDef { + name: "System".to_string(), + module_path: Vec::new(), + methods: vec![make_request_method("handshake", u8::MAX)], + docs: None, + }], + public_trait_order: vec!["System".to_string()], + types: versioned_request_test_types(), + framework_types: Vec::new(), + }; + + let error = generate_client(&api, "testhash") + .expect_err("an inferred response id beyond u8 must be rejected"); + assert!( + error.to_string().contains("wire id overflow"), + "unexpected error: {error}" + ); + } + + #[test] + fn test_client_catalog_rejects_subscription_id_overflow() { + let api = ApiDefinition { + traits: vec![TraitDef { + name: "Account".to_string(), + module_path: Vec::new(), + methods: vec![make_subscription_method("connection_status_subscribe", 253)], + docs: None, + }], + public_trait_order: vec!["Account".to_string()], + types: Vec::new(), + framework_types: Vec::new(), + }; + + let error = generate_client(&api, "testhash") + .expect_err("an inferred receive id beyond u8 must be rejected"); + assert!( + error.to_string().contains("wire id overflow"), + "unexpected error: {error}" + ); + } + fn parse_entries(src: &str) -> Vec<(u8, String)> { // Each method's ids are emitted as a named const, e.g. // pub const PREIMAGE_SUBMIT: RequestFrameIds = RequestFrameIds { diff --git a/rust/crates/truapi-codegen/src/rust/client.rs b/rust/crates/truapi-codegen/src/rust/client.rs new file mode 100644 index 000000000..35214f38a --- /dev/null +++ b/rust/crates/truapi-codegen/src/rust/client.rs @@ -0,0 +1,302 @@ +//! no_std Rust client-catalog generation. + +use anyhow::{Result, bail}; +use convert_case::{Case, Casing}; +use std::fmt::Write; + +use super::{module_for_trait, wire_method_name, wire_table::infer_id}; +use crate::rustdoc::{ApiDefinition, MethodDef, MethodKind, ReturnType, TraitDef, TypeRef}; + +pub fn generate_client(api: &ApiDefinition, schema_hash: &str) -> Result { + let mut out = String::new(); + writeln!(out, "//! Canonical TrUAPI client method catalog.")?; + writeln!(out, "//!")?; + writeln!(out, "//! Auto-generated by truapi-codegen. Do not edit.\n")?; + writeln!(out, "use super::*;\n")?; + writeln!(out, "/// Fingerprint of the generated wire contract.")?; + writeln!( + out, + "pub const TRUAPI_WIRE_SCHEMA_HASH: &str = \"{schema_hash}\";\n" + )?; + + let mut app = Vec::new(); + let mut widget = Vec::new(); + let mut worker = Vec::new(); + let mut worker_only = Vec::new(); + + for trait_name in &api.public_trait_order { + let service = api + .traits + .iter() + .find(|candidate| candidate.name == *trait_name) + .ok_or_else(|| anyhow::anyhow!("public trait `{trait_name}` was not extracted"))?; + let requirement = execution_requirement(service)?; + for method in &service.methods { + let marker = marker_name(service, method); + emit_method(&mut out, service, method, requirement, &marker)?; + match requirement { + None => { + app.push(marker.clone()); + widget.push(marker.clone()); + worker.push(marker); + } + Some("App") => app.push(marker), + Some("Widget") => widget.push(marker), + Some("Worker") => { + worker.push(marker.clone()); + worker_only.push(marker); + } + Some(other) => bail!("unsupported execution requirement `{other}`"), + } + } + } + + emit_catalog(&mut out, "APP_METHODS", &app)?; + emit_catalog(&mut out, "WIDGET_METHODS", &widget)?; + emit_catalog(&mut out, "WORKER_METHODS", &worker)?; + emit_catalog(&mut out, "WORKER_ONLY_METHODS", &worker_only)?; + Ok(out) +} + +fn execution_requirement(service: &TraitDef) -> Result> { + let requirement = service.required_execution(); + if let Some(value) = requirement + && !matches!(value, "App" | "Widget" | "Worker") + { + bail!( + "service `{}` has unknown execution requirement `{value}`", + service.name + ); + } + Ok(requirement) +} + +fn marker_name(service: &TraitDef, method: &MethodDef) -> String { + format!("{}_{}", service.name, method.name).to_case(Case::Pascal) +} + +fn emit_method( + out: &mut String, + service: &TraitDef, + method: &MethodDef, + requirement: Option<&str>, + marker: &str, +) -> Result<()> { + let module = module_for_trait(&service.name); + let wire_name = wire_method_name(&service.name, &method.name); + let execution = requirement + .map(|value| format!("Some(ExecutionKind::{value})")) + .unwrap_or_else(|| "None".to_string()); + let direction = if method.wire.host_initiated { + "Direction::HostToProduct" + } else { + "Direction::ProductToHost" + }; + let kind = match method.kind { + MethodKind::Request => "MethodKind::Request", + MethodKind::Subscription => "MethodKind::Subscription", + MethodKind::ResultSubscription => "MethodKind::ResultSubscription", + }; + let wire = match method.kind { + MethodKind::Request => { + let request_id = method + .wire + .request_id + .ok_or_else(|| anyhow::anyhow!("method `{wire_name}` is missing request_id"))?; + let response_id = infer_id(method.wire.response_id, request_id, 1, &wire_name)?; + format!( + "MethodWire::Request(RequestFrameIds {{ request_id: {request_id}, response_id: {response_id} }})" + ) + } + MethodKind::Subscription | MethodKind::ResultSubscription => { + let start_id = method + .wire + .start_id + .ok_or_else(|| anyhow::anyhow!("method `{wire_name}` is missing start_id"))?; + let stop_id = infer_id(method.wire.stop_id, start_id, 1, &wire_name)?; + let interrupt_id = infer_id(method.wire.interrupt_id, start_id, 2, &wire_name)?; + let receive_id = infer_id(method.wire.receive_id, start_id, 3, &wire_name)?; + format!( + "MethodWire::Subscription(SubscriptionFrameIds {{ start_id: {start_id}, stop_id: {stop_id}, interrupt_id: {interrupt_id}, receive_id: {receive_id} }})" + ) + } + }; + let request_name = request_type(method, &module)?; + let (response_name, error_name) = match &method.return_type { + ReturnType::Result { ok, err } => ( + rust_type(ok, &module)?, + Some(rust_type(call_error_domain(err)?, &module)?), + ), + ReturnType::Subscription(item) => (rust_type(item, &module)?, None), + ReturnType::ResultSubscription { item, err } => ( + rust_type(item, &module)?, + Some(rust_type(call_error_domain(err)?, &module)?), + ), + }; + + writeln!(out, "/// `{wire_name}` method marker.")?; + writeln!(out, "pub struct {marker};")?; + writeln!(out, "impl {marker} {{")?; + writeln!( + out, + " /// Canonical metadata and frame ids for this method." + )?; + writeln!( + out, + " pub const DESCRIPTOR: MethodDescriptor = MethodDescriptor {{" + )?; + writeln!(out, " service: \"{}\",", service.name)?; + writeln!(out, " method: \"{}\",", method.name)?; + writeln!(out, " wire_name: \"{wire_name}\",")?; + writeln!(out, " request_type: \"{request_name}\",")?; + writeln!(out, " response_type: \"{response_name}\",")?; + match error_name { + Some(error) => writeln!(out, " error_type: Some(\"{error}\"),")?, + None => writeln!(out, " error_type: None,")?, + } + writeln!(out, " kind: {kind},")?; + writeln!(out, " direction: {direction},")?; + writeln!(out, " required_execution: {execution},")?; + writeln!(out, " sensitive: {},", method.wire.sensitive)?; + writeln!(out, " wire: {wire},")?; + writeln!(out, " }};")?; + writeln!(out, "}}")?; + + let request = request_type(method, &module)?; + match ( + &method.kind, + &method.return_type, + method.wire.host_initiated, + ) { + (MethodKind::Request, ReturnType::Result { ok, err }, false) => { + let response = rust_type(ok, &module)?; + let error = rust_type(call_error_domain(err)?, &module)?; + writeln!(out, "impl RequestMethod for {marker} {{")?; + writeln!(out, " type Request = {request};")?; + writeln!(out, " type Response = {response};")?; + writeln!(out, " type Error = {error};")?; + writeln!( + out, + " const RESPONSE_VERSIONED: bool = {};", + !matches!(ok, TypeRef::Unit) + )?; + writeln!( + out, + " const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR;" + )?; + writeln!(out, "}}\n")?; + } + (MethodKind::Subscription, ReturnType::Subscription(item), false) => { + let item = rust_type(item, &module)?; + writeln!(out, "impl SubscriptionMethod for {marker} {{")?; + writeln!(out, " type Request = {request};")?; + writeln!(out, " type Item = {item};")?; + writeln!( + out, + " const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR;" + )?; + writeln!(out, "}}\n")?; + } + (MethodKind::ResultSubscription, ReturnType::ResultSubscription { item, err }, false) => { + let item = rust_type(item, &module)?; + let error = rust_type(call_error_domain(err)?, &module)?; + writeln!(out, "impl ResultSubscriptionMethod for {marker} {{")?; + writeln!(out, " type Request = {request};")?; + writeln!(out, " type Item = {item};")?; + writeln!(out, " type Error = {error};")?; + writeln!( + out, + " const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR;" + )?; + writeln!(out, "}}\n")?; + } + (MethodKind::Subscription, ReturnType::Subscription(item), true) => { + let item = rust_type(item, &module)?; + writeln!(out, "impl HostSubscriptionMethod for {marker} {{")?; + writeln!(out, " type Request = {request};")?; + writeln!(out, " type Item = {item};")?; + writeln!( + out, + " const DESCRIPTOR: MethodDescriptor = Self::DESCRIPTOR;" + )?; + writeln!(out, "}}\n")?; + } + _ => bail!("method `{wire_name}` has unsupported kind/return/direction combination"), + } + Ok(()) +} + +fn request_type(method: &MethodDef, module: &str) -> Result { + match method.params.as_slice() { + [] => Ok("()".to_string()), + [param] => rust_type(¶m.type_ref, module), + params => bail!( + "method `{}` has {} wire parameters; expected at most one request wrapper", + method.name, + params.len() + ), + } +} + +fn call_error_domain(error: &TypeRef) -> Result<&TypeRef> { + match error { + TypeRef::Named { name, args } if name == "CallError" && args.len() == 1 => Ok(&args[0]), + _ => bail!("method error is not CallError: {error:?}"), + } +} + +fn rust_type(value: &TypeRef, module: &str) -> Result { + Ok(match value { + TypeRef::Primitive(name) if name == "String" => "alloc::string::String".to_string(), + TypeRef::Primitive(name) => name.clone(), + TypeRef::Named { name, args } if name == "String" && args.is_empty() => { + "alloc::string::String".to_string() + } + TypeRef::Named { name, args } if name == "Vec" && args.len() == 1 => { + format!("alloc::vec::Vec<{}>", rust_type(&args[0], module)?) + } + TypeRef::Named { name, args } if name == "Option" && args.len() == 1 => { + format!("Option<{}>", rust_type(&args[0], module)?) + } + TypeRef::Named { name, args } if name == "Infallible" && args.is_empty() => { + "core::convert::Infallible".to_string() + } + TypeRef::Named { name, args } if args.is_empty() => { + format!("truapi::versioned::{module}::{name}") + } + TypeRef::Named { name, args } => { + let args = args + .iter() + .map(|arg| rust_type(arg, module)) + .collect::>>()? + .join(", "); + format!("truapi::versioned::{module}::{name}<{args}>") + } + TypeRef::Vec(inner) => format!("alloc::vec::Vec<{}>", rust_type(inner, module)?), + TypeRef::Option(inner) => format!("Option<{}>", rust_type(inner, module)?), + TypeRef::Tuple(items) => { + let mut rendered = items + .iter() + .map(|item| rust_type(item, module)) + .collect::>>()? + .join(", "); + if items.len() == 1 { + rendered.push(','); + } + format!("({rendered})") + } + TypeRef::Array(inner, len) => format!("[{}; {len}]", rust_type(inner, module)?), + TypeRef::Generic(name) => bail!("unresolved generic type `{name}` in method surface"), + TypeRef::Unit => "()".to_string(), + }) +} + +fn emit_catalog(out: &mut String, name: &str, markers: &[String]) -> Result<()> { + writeln!(out, "/// Generated `{name}` execution catalog.")?; + writeln!(out, "pub const {name}: &[MethodDescriptor] = &[")?; + for marker in markers { + writeln!(out, " {marker}::DESCRIPTOR,")?; + } + writeln!(out, "];\n")?; + Ok(()) +} diff --git a/rust/crates/truapi-codegen/src/rust/wire_table.rs b/rust/crates/truapi-codegen/src/rust/wire_table.rs index fd23359cf..0baef8902 100644 --- a/rust/crates/truapi-codegen/src/rust/wire_table.rs +++ b/rust/crates/truapi-codegen/src/rust/wire_table.rs @@ -132,7 +132,12 @@ fn method_entry(trait_def: &TraitDef, method: &MethodDef) -> Result } } -fn infer_id(explicit: Option, anchor: u8, offset: u8, method_name: &str) -> Result { +pub(super) fn infer_id( + explicit: Option, + anchor: u8, + offset: u8, + method_name: &str, +) -> Result { if let Some(id) = explicit { return Ok(id); } diff --git a/rust/crates/truapi-host-cli/src/frame_server.rs b/rust/crates/truapi-host-cli/src/frame_server.rs index 79a7c13ca..9f500bc21 100644 --- a/rust/crates/truapi-host-cli/src/frame_server.rs +++ b/rust/crates/truapi-host-cli/src/frame_server.rs @@ -108,6 +108,9 @@ pub trait ProductRuntimeFactory: Send + Sync + 'static { } } +// async-trait's generated boxed Future is already must-use; newer Clippy +// otherwise reports the macro's duplicate annotation on this private trait. +#[allow(clippy::double_must_use)] #[async_trait::async_trait] trait ConnectionRuntime: Send + Sync + 'static { async fn receive_frame(&self, frame: Vec) -> Result<(), ProductRuntimeError>; diff --git a/rust/crates/truapi-polkavm-host/Cargo.toml b/rust/crates/truapi-polkavm-host/Cargo.toml new file mode 100644 index 000000000..1428cf046 --- /dev/null +++ b/rust/crates/truapi-polkavm-host/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "truapi-polkavm-host" +version = "0.2.0" +edition.workspace = true +description = "Optional composition of the TrUAPI server and PolkaVM host runtime" +license = "MIT" +repository = "https://github.com/paritytech/host-rust-core" +publish = false + +[lib] +crate-type = ["rlib"] + +[dependencies] +polkavm-host-runtime = { git = "https://github.com/paritytech/polkavm-host-runtime.git", rev = "be1f15793e127cb5702d331fa8035bafc070c99a", version = "=0.2.0", features = ["ffi", "native-gpu"] } +truapi-server = { path = "../truapi-server" } + +[lints] +workspace = true diff --git a/rust/crates/truapi-polkavm-host/src/lib.rs b/rust/crates/truapi-polkavm-host/src/lib.rs new file mode 100644 index 000000000..a70b0f349 --- /dev/null +++ b/rust/crates/truapi-polkavm-host/src/lib.rs @@ -0,0 +1,37 @@ +//! Optional composition of the TrUAPI server and PolkaVM host runtime. +//! +//! The base [`truapi_server`] remains independent of PolkaVM. Native hosts that +//! need both surfaces link this crate, which pins one reviewed runtime revision. + +/// The pinned PolkaVM host runtime API. +pub use polkavm_host_runtime; +/// The PolkaVM-independent TrUAPI server API. +pub use truapi_server; + +/// Version of this optional composition crate. +pub const TRUAPI_POLKAVM_HOST_VERSION: &str = env!("CARGO_PKG_VERSION"); +/// Version of the pinned PolkaVM host runtime. +pub const POLKAVM_HOST_RUNTIME_VERSION: &str = "0.2.0"; +/// Immutable source revision of the pinned PolkaVM host runtime. +pub const POLKAVM_HOST_RUNTIME_SOURCE_REVISION: &str = "be1f15793e127cb5702d331fa8035bafc070c99a"; + +#[cfg(test)] +mod tests { + const MANIFEST: &str = include_str!("../Cargo.toml"); + + #[test] + fn test_constants_match_pinned_runtime_dependency() { + let dependency = MANIFEST + .lines() + .find(|line| line.starts_with("polkavm-host-runtime = ")) + .expect("polkavm-host-runtime dependency line"); + assert!(dependency.contains(&format!( + "rev = \"{}\"", + super::POLKAVM_HOST_RUNTIME_SOURCE_REVISION + ))); + assert!(dependency.contains(&format!( + "version = \"={}\"", + super::POLKAVM_HOST_RUNTIME_VERSION + ))); + } +} diff --git a/rust/crates/truapi/Cargo.toml b/rust/crates/truapi/Cargo.toml index 590fb0d5c..f38a6637c 100644 --- a/rust/crates/truapi/Cargo.toml +++ b/rust/crates/truapi/Cargo.toml @@ -6,18 +6,24 @@ license.workspace = true description = "TrUAPI trait and type definitions" [dependencies] -async-trait = "0.1" -derive_more = { version = "2", features = ["display"] } -futures = "0.3" -hex = "0.4" -parity-scale-codec = { version = "3", features = ["derive"] } +async-trait = { version = "0.1", optional = true } +derive_more = { version = "2", default-features = false, features = ["display"] } +futures = { version = "0.3", optional = true } +hex = { version = "0.4", default-features = false, features = ["alloc"] } +parity-scale-codec = { version = "3", default-features = false, features = ["derive"] } truapi-macros = { path = "../truapi-macros" } uniffi = { workspace = true, optional = true } [features] -default = [] +default = ["runtime"] +# Async host traits, cancellation, and subscription primitives. +runtime = [ + "dep:async-trait", + "dep:futures", + "parity-scale-codec/std", +] # FFI derives on the protocol types consumed by native hosts. -uniffi = ["dep:uniffi"] +uniffi = ["runtime", "dep:uniffi"] [lints] workspace = true diff --git a/rust/crates/truapi/src/lib.rs b/rust/crates/truapi/src/lib.rs index 06d3557f4..6b1f43d93 100644 --- a/rust/crates/truapi/src/lib.rs +++ b/rust/crates/truapi/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(not(feature = "runtime"), no_std)] #![allow( clippy::double_must_use, reason = "async-trait generates must_use futures for async trait methods" @@ -11,21 +12,35 @@ //! still guarantee `Send` futures. Implementations must annotate their impl //! blocks with `#[truapi::async_trait]`. +extern crate alloc; + +use alloc::string::String; +#[cfg(feature = "runtime")] +use alloc::{boxed::Box, format, vec::Vec}; use core::convert::Infallible; +#[cfg(feature = "runtime")] use core::fmt; +#[cfg(feature = "runtime")] use core::future::Future; +#[cfg(feature = "runtime")] use core::mem; +#[cfg(feature = "runtime")] use core::pin::Pin; +#[cfg(feature = "runtime")] use core::task::{Context, Poll, Waker}; +#[cfg(feature = "runtime")] use core::time::Duration; -use std::sync::Arc; -use std::sync::Mutex; +#[cfg(feature = "runtime")] +use std::sync::{Arc, Mutex}; +#[cfg(feature = "runtime")] use futures::Stream; use parity_scale_codec::{Decode, Encode}; +#[cfg(feature = "runtime")] pub use async_trait::async_trait; +#[cfg(feature = "runtime")] pub mod api; pub mod v01; pub mod versioned; @@ -243,17 +258,20 @@ pub type FrameworkOnlyError = CallError; /// tokens fire when a runtime explicitly cancels them or attaches a timeout. /// Subscription runtimes can cancel this token when the peer sends `_stop` or /// disconnects. +#[cfg(feature = "runtime")] #[derive(Clone, Default)] pub struct CancellationToken { inner: Arc, } #[derive(Default)] +#[cfg(feature = "runtime")] struct CancellationInner { state: Mutex, } #[derive(Default)] +#[cfg(feature = "runtime")] struct CancellationState { reason: Option, next_id: u64, @@ -261,6 +279,7 @@ struct CancellationState { } /// Cause attached to a cancelled call. +#[cfg(feature = "runtime")] #[derive(Debug, Clone, PartialEq, Eq, derive_more::Display)] pub enum CancellationReason { /// The caller or runtime explicitly cancelled the call. @@ -275,6 +294,7 @@ pub enum CancellationReason { } /// Render a timeout as whole seconds when possible, milliseconds otherwise. +#[cfg(feature = "runtime")] fn format_timeout(timeout: &Duration) -> String { if timeout.subsec_millis() == 0 { format!("{}s", timeout.as_secs()) @@ -284,11 +304,13 @@ fn format_timeout(timeout: &Duration) -> String { } /// Future resolved when a [`CancellationToken`] is cancelled. +#[cfg(feature = "runtime")] pub struct CancellationFuture { inner: Arc, id: Option, } +#[cfg(feature = "runtime")] impl fmt::Debug for CancellationToken { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("CancellationToken") @@ -297,6 +319,7 @@ impl fmt::Debug for CancellationToken { } } +#[cfg(feature = "runtime")] impl CancellationToken { /// Mark the token as cancelled. pub fn cancel(&self) { @@ -342,6 +365,7 @@ impl CancellationToken { } } +#[cfg(feature = "runtime")] impl Future for CancellationFuture { type Output = CancellationReason; @@ -373,6 +397,7 @@ impl Future for CancellationFuture { } } +#[cfg(feature = "runtime")] impl Drop for CancellationFuture { fn drop(&mut self) { let Some(id) = self.id.take() else { @@ -387,6 +412,7 @@ impl Drop for CancellationFuture { } /// Ambient context passed to every trait method. +#[cfg(feature = "runtime")] #[derive(Clone, Default)] pub struct CallContext { request_id: RequestId, @@ -394,6 +420,7 @@ pub struct CallContext { timeout: Option, } +#[cfg(feature = "runtime")] impl CallContext { /// Construct a context bound to the given `request_id` with a fresh cancellation token. pub fn with_request_id(request_id: RequestId) -> Self { @@ -436,10 +463,12 @@ impl CallContext { /// Handle to an active subscription. Implements [`Stream`] to yield values /// pushed by the host. Drop to unsubscribe. +#[cfg(feature = "runtime")] pub struct Subscription { inner: Pin + Send>>, } +#[cfg(feature = "runtime")] impl Stream for Subscription { type Item = T; @@ -448,6 +477,7 @@ impl Stream for Subscription { } } +#[cfg(feature = "runtime")] impl Subscription { /// Creates a new subscription from a boxed stream. pub fn new(stream: Pin + Send>>) -> Self { @@ -465,7 +495,7 @@ impl Subscription { } } -#[cfg(test)] +#[cfg(all(test, feature = "runtime"))] mod tests { use super::*; diff --git a/rust/crates/truapi/src/v01/account.rs b/rust/crates/truapi/src/v01/account.rs index 56fadf35a..b1eabcf05 100644 --- a/rust/crates/truapi/src/v01/account.rs +++ b/rust/crates/truapi/src/v01/account.rs @@ -1,4 +1,5 @@ use crate::v01::transaction::GenesisHash; +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; /// Account selector within a product subtree. Encodes as diff --git a/rust/crates/truapi/src/v01/chain.rs b/rust/crates/truapi/src/v01/chain.rs index 589310cf2..09dff605f 100644 --- a/rust/crates/truapi/src/v01/chain.rs +++ b/rust/crates/truapi/src/v01/chain.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; use super::common::GenericError; diff --git a/rust/crates/truapi/src/v01/chat.rs b/rust/crates/truapi/src/v01/chat.rs index df983f1fe..f833ede05 100644 --- a/rust/crates/truapi/src/v01/chat.rs +++ b/rust/crates/truapi/src/v01/chat.rs @@ -1,3 +1,5 @@ +use alloc::{string::String, vec::Vec}; + /// UI tree types for host-rendered custom chat messages. pub mod custom_renderer; pub use custom_renderer::*; diff --git a/rust/crates/truapi/src/v01/chat/custom_renderer.rs b/rust/crates/truapi/src/v01/chat/custom_renderer.rs index ad0d1ed6c..ec5ed0b98 100644 --- a/rust/crates/truapi/src/v01/chat/custom_renderer.rs +++ b/rust/crates/truapi/src/v01/chat/custom_renderer.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Compact, Decode, Encode, OptionBool}; /// A size/dimension value (logical pixels) used across the custom renderer. diff --git a/rust/crates/truapi/src/v01/coin_payment.rs b/rust/crates/truapi/src/v01/coin_payment.rs index 71580a6e6..12b84771a 100644 --- a/rust/crates/truapi/src/v01/coin_payment.rs +++ b/rust/crates/truapi/src/v01/coin_payment.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; /// RFC 0017 CoinPayment purse identifier. diff --git a/rust/crates/truapi/src/v01/common.rs b/rust/crates/truapi/src/v01/common.rs index 49cbe1228..e06f31633 100644 --- a/rust/crates/truapi/src/v01/common.rs +++ b/rust/crates/truapi/src/v01/common.rs @@ -1,3 +1,4 @@ +use alloc::string::String; use parity_scale_codec::{Decode, Encode}; /// Generic error payload carrying a human-readable reason string. Used by many diff --git a/rust/crates/truapi/src/v01/entropy.rs b/rust/crates/truapi/src/v01/entropy.rs index 7a56e4524..1039a4a6d 100644 --- a/rust/crates/truapi/src/v01/entropy.rs +++ b/rust/crates/truapi/src/v01/entropy.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; /// Error from [`crate::api::Entropy::derive`] (RFC 0007). diff --git a/rust/crates/truapi/src/v01/local_storage.rs b/rust/crates/truapi/src/v01/local_storage.rs index 3bd56307b..82610a926 100644 --- a/rust/crates/truapi/src/v01/local_storage.rs +++ b/rust/crates/truapi/src/v01/local_storage.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use derive_more::Display; use parity_scale_codec::{Decode, Encode}; diff --git a/rust/crates/truapi/src/v01/locale.rs b/rust/crates/truapi/src/v01/locale.rs index bc244e19f..f3168d83c 100644 --- a/rust/crates/truapi/src/v01/locale.rs +++ b/rust/crates/truapi/src/v01/locale.rs @@ -1,3 +1,4 @@ +use alloc::string::String; use parity_scale_codec::{Decode, Encode}; /// Locale the host currently presents its interface in, pushed to subscribers. diff --git a/rust/crates/truapi/src/v01/notifications.rs b/rust/crates/truapi/src/v01/notifications.rs index d61633cc5..218d9201a 100644 --- a/rust/crates/truapi/src/v01/notifications.rs +++ b/rust/crates/truapi/src/v01/notifications.rs @@ -1,3 +1,4 @@ +use alloc::string::String; use parity_scale_codec::{Decode, Encode}; /// Opaque identifier for a push notification, unique per product. diff --git a/rust/crates/truapi/src/v01/payment.rs b/rust/crates/truapi/src/v01/payment.rs index 7b26901c3..ed3c14f3c 100644 --- a/rust/crates/truapi/src/v01/payment.rs +++ b/rust/crates/truapi/src/v01/payment.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; use super::account::DerivationIndex; diff --git a/rust/crates/truapi/src/v01/permissions.rs b/rust/crates/truapi/src/v01/permissions.rs index 7f8e902b1..4d961ff0a 100644 --- a/rust/crates/truapi/src/v01/permissions.rs +++ b/rust/crates/truapi/src/v01/permissions.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use derive_more::Display; use parity_scale_codec::{Decode, Encode}; diff --git a/rust/crates/truapi/src/v01/preimage.rs b/rust/crates/truapi/src/v01/preimage.rs index 808066749..4ec9654dc 100644 --- a/rust/crates/truapi/src/v01/preimage.rs +++ b/rust/crates/truapi/src/v01/preimage.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; /// Preimage submission error. diff --git a/rust/crates/truapi/src/v01/resource_allocation.rs b/rust/crates/truapi/src/v01/resource_allocation.rs index 932ec1929..d9a1ef59a 100644 --- a/rust/crates/truapi/src/v01/resource_allocation.rs +++ b/rust/crates/truapi/src/v01/resource_allocation.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; use super::account::DerivationIndex; diff --git a/rust/crates/truapi/src/v01/signing.rs b/rust/crates/truapi/src/v01/signing.rs index 45459878d..81e0ca33c 100644 --- a/rust/crates/truapi/src/v01/signing.rs +++ b/rust/crates/truapi/src/v01/signing.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; use super::ProductAccountId; diff --git a/rust/crates/truapi/src/v01/statement_store.rs b/rust/crates/truapi/src/v01/statement_store.rs index f494a53af..a18c3a88f 100644 --- a/rust/crates/truapi/src/v01/statement_store.rs +++ b/rust/crates/truapi/src/v01/statement_store.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; use super::ProductAccountId; diff --git a/rust/crates/truapi/src/v01/system.rs b/rust/crates/truapi/src/v01/system.rs index de67504fd..3ef3ec913 100644 --- a/rust/crates/truapi/src/v01/system.rs +++ b/rust/crates/truapi/src/v01/system.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use derive_more::Display; use parity_scale_codec::{Decode, Encode}; diff --git a/rust/crates/truapi/src/v01/theme.rs b/rust/crates/truapi/src/v01/theme.rs index bf7fd9edb..eb513ea32 100644 --- a/rust/crates/truapi/src/v01/theme.rs +++ b/rust/crates/truapi/src/v01/theme.rs @@ -1,3 +1,4 @@ +use alloc::string::String; use parity_scale_codec::{Decode, Encode}; /// Identifies a named theme. diff --git a/rust/crates/truapi/src/v01/transaction.rs b/rust/crates/truapi/src/v01/transaction.rs index b88e840f6..c2c50aa0a 100644 --- a/rust/crates/truapi/src/v01/transaction.rs +++ b/rust/crates/truapi/src/v01/transaction.rs @@ -1,3 +1,4 @@ +use alloc::{string::String, vec::Vec}; use parity_scale_codec::{Decode, Encode}; use super::ProductAccountId; diff --git a/rust/crates/truapi/src/versioned/account.rs b/rust/crates/truapi/src/versioned/account.rs index fd0bfd607..2c7c2a1c0 100644 --- a/rust/crates/truapi/src/versioned/account.rs +++ b/rust/crates/truapi/src/versioned/account.rs @@ -1,4 +1,5 @@ //! Versioned wrappers for [`Account`](crate::api::Account) methods. +use alloc::vec::Vec; use crate::v01; diff --git a/rust/crates/truapi/src/versioned/preimage.rs b/rust/crates/truapi/src/versioned/preimage.rs index 61bf4b2f3..ebd398071 100644 --- a/rust/crates/truapi/src/versioned/preimage.rs +++ b/rust/crates/truapi/src/versioned/preimage.rs @@ -1,4 +1,5 @@ //! Versioned wrappers for [`Preimage`](crate::api::Preimage) methods. +use alloc::vec::Vec; use crate::v01; diff --git a/scripts/codegen.sh b/scripts/codegen.sh index 4221535fe..fc27ba677 100755 --- a/scripts/codegen.sh +++ b/scripts/codegen.sh @@ -38,6 +38,7 @@ cargo run -p truapi-codegen -- \ --playground-output js/packages/truapi/src/playground \ --client-examples-output playground/test/generated/examples \ --rust-output rust/crates/truapi-server/src/generated \ + --rust-client-output rust/crates/truapi-client/src/generated.rs \ --platform-input target/doc/truapi_platform.json \ --platform-ts-output js/packages/truapi-host/src/generated \ --platform-wasm-adapter-output js/packages/truapi-host/src/generated \ @@ -46,6 +47,7 @@ cargo run -p truapi-codegen -- \ --codec-version 1 rustfmt +"$NIGHTLY_TOOLCHAIN" --edition 2024 \ + rust/crates/truapi-client/src/generated.rs \ rust/crates/truapi-server/src/generated/dispatcher.rs \ rust/crates/truapi-server/src/generated/wire_table.rs \ rust/crates/truapi-server/src/wasm/generated_bridge.rs @@ -82,5 +84,6 @@ echo "Generated client at js/packages/truapi/src/generated/" echo "Generated playground metadata at js/packages/truapi/src/playground/codegen/" echo "Generated client examples at playground/test/generated/examples/" echo "Generated Rust dispatcher at rust/crates/truapi-server/src/generated/" +echo "Generated no-std Rust client catalog at rust/crates/truapi-client/src/generated.rs" echo "Generated host-callbacks WASM adapter at js/packages/truapi-host/src/generated/" echo "Generated Rust WASM bridge at rust/crates/truapi-server/src/wasm/generated_bridge.rs"