From db045c54feb63d84cc3e2cd6cbb42d945cf91495 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Fri, 23 Jun 2023 15:23:05 +0200 Subject: [PATCH 01/28] parachain rpc lists --- subxt/examples/connect_to_a_parachain.rs | 49 ++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 subxt/examples/connect_to_a_parachain.rs diff --git a/subxt/examples/connect_to_a_parachain.rs b/subxt/examples/connect_to_a_parachain.rs new file mode 100644 index 0000000000..655ffbbe4e --- /dev/null +++ b/subxt/examples/connect_to_a_parachain.rs @@ -0,0 +1,49 @@ +//! In this example we will connect to a parachain and subscribe to its blocks. +//! There are many parachains on Polkadot and Kusama. In order to connect to a +//! chain we first need to fetch its metadata. This requires us to know a valid +//! RPC endpoint of the chain. +//! The [Substrate Chains Runtime Api Doc Center](https://substrate.rs/index.html) lists parachains +//! on Polkadot and Kusama and gives us a list of RPC endpoints for each parachain. Alternatively +//! we can also look for the RPC endpoint of a chain via [Polkadot.js](https://polkadot.js.org/apps/). +//! In the side menu, you can select a Polkadot/Kusama parachain. The hit the "Switch" button and +//! let the page load the chains data. The RPC endpoint url can be found as part of the url. +//! You can also open the console, to see the RPC endpoint url printed without URL-encoded special characters. +//! +//! Let's go through an example for the "Ajuna" parachain on Polkadot. +//! Selecting it in the [Polkadot.js](https://polkadot.js.org/apps/) menu, then opening the console +//! lets us observe the following output: `WS endpoint= wss://rpc-parachain.ajuna.network` +//! +//! We can now get the metadata of the chain via the subxt-cli tool. +//! It is important to note that we need to add a `:433` as the port number here: +//! ```txt +//! metadata --url wss://rpc-parachain.ajuna.network:443 > artifacts/ajuna_metadata.scale +//! ``` +//! +//! This allows us to construct a module with the ajuna types, calls, +//! +//! + +use subxt::{Config, OnlineClient, PolkadotConfig, SubstrateConfig}; + + +/// Default set of commonly used types by Polkadot nodes. +pub enum AjunaConfig {} + +impl Config for AjunaConfig { + type Index = ::Index; + type Hash = ::Hash; + type AccountId = ::AccountId; + type Address = ::Address; + type Signature = ::Signature; + type Hasher = ::Hasher; + type Header = ::Header; + type ExtrinsicParams = ::ExtrinsicParams; +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Create a new API client, configured to talk to Polkadot nodes. + let api = OnlineClient::::new().await?; + + Ok(()) +} From a996f4216fcb2132e408fde760cd263acdc0251d Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Thu, 29 Jun 2023 21:26:26 +0200 Subject: [PATCH 02/28] guide almost done --- .gitignore | 2 + examples/parachain-example/Cargo.lock | 3664 +++++++++++++++++ examples/parachain-example/Cargo.toml | 21 + .../parachain-example/metadata/Cargo.toml | 7 + .../parachain-example/metadata/src/lib.rs | 2 + .../metadata/statemint_metadata.scale | Bin 0 -> 158746 bytes examples/parachain-example/src/main.rs | 257 ++ examples/parachain-example/table.md | 10 + subxt/examples/connect_to_a_parachain.rs | 31 +- subxt/src/config/mod.rs | 48 +- 10 files changed, 4024 insertions(+), 18 deletions(-) create mode 100644 examples/parachain-example/Cargo.lock create mode 100644 examples/parachain-example/Cargo.toml create mode 100644 examples/parachain-example/metadata/Cargo.toml create mode 100644 examples/parachain-example/metadata/src/lib.rs create mode 100644 examples/parachain-example/metadata/statemint_metadata.scale create mode 100644 examples/parachain-example/src/main.rs create mode 100644 examples/parachain-example/table.md diff --git a/.gitignore b/.gitignore index 54fbaea00f..e7dc82d631 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ cargo-timing* /examples/wasm-example/dist /examples/wasm-example/target +/examples/parachain-example/target +/examples/parachain-example/metadata/target \ No newline at end of file diff --git a/examples/parachain-example/Cargo.lock b/examples/parachain-example/Cargo.lock new file mode 100644 index 0000000000..c0ee2db56c --- /dev/null +++ b/examples/parachain-example/Cargo.lock @@ -0,0 +1,3664 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom 0.2.10", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + +[[package]] +name = "array-bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-lock" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-trait" +version = "0.1.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "bounded-collections" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "winapi", +] + +[[package]] +name = "constant_time_eq" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-entity" +version = "0.95.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40099d38061b37e505e63f89bab52199037a72b931ad4868d9089ff7268660b0" +dependencies = [ + "serde", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +dependencies = [ + "darling_core 0.20.1", + "darling_macro 0.20.1", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_core" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.22", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +dependencies = [ + "darling_core 0.20.1", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "h2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", + "webpki-roots", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpsee" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-types", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" +dependencies = [ + "futures-util", + "http", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project", + "rustls-native-certs", + "soketto", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util", + "tracing", + "webpki-roots", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +dependencies = [ + "anyhow", + "async-lock", + "async-trait", + "beef", + "futures-channel", + "futures-timer", + "futures-util", + "hyper", + "jsonrpsee-types", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" +dependencies = [ + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core", + "jsonrpsee-types", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memfd" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" +dependencies = [ + "rustix 0.37.20", +] + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "metadata" +version = "0.1.0" +dependencies = [ + "subxt", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.4", + "itoa", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "crc32fast", + "hashbrown 0.13.2", + "indexmap 1.9.3", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "parachain-example" +version = "0.1.0" +dependencies = [ + "futures", + "metadata", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "sp-core", + "sp-runtime", + "subxt", + "tokio", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2287753623c76f953acd29d15d8100bcab84d29db78fb6f352adb3c53e83b967" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6937b5e67bfba3351b87b040d48352a2fcb6ad72f81855412ce97b45c8f110" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.0", +] + +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "regex" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustix" +version = "0.36.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustix" +version = "0.37.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "scale-bits" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd7aca73785181cc41f0bbe017263e682b585ca660540ba569133901d013ecf" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0459d00b0dbd2e765009924a78ef36b2ff7ba116292d732f00eb0ed8e465d15" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode-derive", + "scale-info", + "smallvec", + "thiserror", +] + +[[package]] +name = "scale-decode-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4391f0dfbb6690f035f6d2a15d6a12f88cc5395c36bcc056db07ffa2a90870ec" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0401b7cdae8b8aa33725f3611a051358d5b32887ecaa0fda5953a775b2d4d76" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-encode-derive", + "scale-info", + "smallvec", + "thiserror", +] + +[[package]] +name = "scale-encode-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "316e0fb10ec0fee266822bd641bab5e332a4ab80ef8c5b5ff35e5401a394f5a6" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad560913365790f17cbf12479491169f01b9d46d29cfc7422bf8c64bdc61b731" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19df9bd9ace6cc2fe19387c96ce677e823e07d017ceed253e7bb3d1d1bd9c73b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-value" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2096d36e94ce9bf87d8addb752423b6b19730dc88edd7cc452bb2b90573f7a7" +dependencies = [ + "base58", + "blake2", + "either", + "frame-metadata", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "serde", + "thiserror", + "yap", +] + +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.3", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "serde_json" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "futures", + "httparse", + "log", + "rand 0.8.5", + "sha-1", +] + +[[package]] +name = "sp-application-crypto" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899492ea547816d5dfe9a5a2ecc32f65a7110805af6da3380aa4902371b31dc2" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6020576e544c6824a51d651bc8df8e6ab67cd59f1c9ac09868bb81a5199ded" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18d9e2f67d8661f9729f35347069ac29d92758b59135176799db966947a7336" +dependencies = [ + "array-bytes", + "bitflags", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log", + "merlin", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand 0.8.5", + "regex", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-core-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee599a8399448e65197f9a6cee338ad192e9023e35e31f22382964c3c174c68" +dependencies = [ + "blake2b_simd", + "byteorder", + "digest 0.10.7", + "sha2 0.10.7", + "sha3", + "sp-std", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "sp-externalities" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f71c671e01a8ca60da925d43a1b351b69626e268b8837f8371e320cf1dd100" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std", + "sp-storage", +] + +[[package]] +name = "sp-io" +version = "23.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d597e35a9628fe7454b08965b2442e3ec0f264b0a90d41328e87422cec02e99" +dependencies = [ + "bytes", + "ed25519", + "ed25519-dalek", + "futures", + "libsecp256k1", + "log", + "parity-scale-codec", + "rustversion", + "secp256k1", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be3cdd67cc1d9c1db17c5cbc4ec4924054a8437009d167f21f6590797e4aa45" +dependencies = [ + "futures", + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", + "thiserror", +] + +[[package]] +name = "sp-panic-handler" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd2de46003fa8212426838ca71cd42ee36a26480ba9ffea983506ce03131033" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21c5bfc764a1a8259d7e8f7cfd22c84006275a512c958d3ff966c92151e134d5" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e676128182f90015e916f806cba635c8141e341e7abbc45d25525472e1bbce8" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "11.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d5bd5566fe5633ec48dfa35ab152fd29f8a577c21971e1c6db9f28afb9bbb9" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "sp-state-machine" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef45d31f9e7ac648f8899a0cd038a3608f8499028bff55b6c799702592325b6" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std", + "sp-trie", + "thiserror", + "tracing", +] + +[[package]] +name = "sp-std" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53458e3c57df53698b3401ec0934bea8e8cfce034816873c0b0abbd83d7bac0d" + +[[package]] +name = "sp-storage" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94294be83f11d4958cfea89ed5798f0b6605f5defc3a996948848458abbcc18e" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "sp-tracing" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357f7591980dd58305956d32f8f6646d0a8ea9ea0e7e868e46f53b68ddf00cec" +dependencies = [ + "parity-scale-codec", + "sp-std", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4eeb7ef23f79eba8609db79ef9cef242f994f1f87a3c0387b4b5f177fda74" +dependencies = [ + "ahash 0.8.3", + "hash-db", + "hashbrown 0.13.2", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "scale-info", + "schnellru", + "sp-core", + "sp-std", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19c122609ca5d8246be6386888596320d03c7bc880959eaa2c36bcd5acd6846" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std", + "wasmtime", +] + +[[package]] +name = "sp-weights" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45d084c735544f70625b821c3acdbc7a2fc1893ca98b85f1942631284692c75b" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "ss58-registry" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47a8ad42e5fc72d5b1eb104a5546937eaf39843499948bb666d6e93c62423b" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "subxt" +version = "0.29.0" +dependencies = [ + "base58", + "blake2", + "derivative", + "either", + "frame-metadata", + "futures", + "hex", + "impl-serde", + "jsonrpsee", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-core", + "sp-core-hashing", + "sp-runtime", + "subxt-macro", + "subxt-metadata", + "thiserror", + "tracing", +] + +[[package]] +name = "subxt-codegen" +version = "0.29.0" +dependencies = [ + "frame-metadata", + "heck", + "hex", + "jsonrpsee", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "subxt-metadata", + "syn 2.0.22", + "thiserror", + "tokio", +] + +[[package]] +name = "subxt-macro" +version = "0.29.0" +dependencies = [ + "darling 0.20.1", + "proc-macro-error", + "subxt-codegen", + "syn 2.0.22", +] + +[[package]] +name = "subxt-metadata" +version = "0.29.0" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", + "sp-core-hashing", + "thiserror", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.7", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +dependencies = [ + "autocfg", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.22", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wasmparser" +version = "0.102.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48134de3d7598219ab9eaf6b91b15d8e50d31da76b8519fe4ecfcec2cf35104b" +dependencies = [ + "indexmap 1.9.3", + "url", +] + +[[package]] +name = "wasmtime" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f907fdead3153cb9bfb7a93bbd5b62629472dc06dee83605358c64c52ed3dda9" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "indexmap 1.9.3", + "libc", + "log", + "object", + "once_cell", + "paste", + "psm", + "serde", + "target-lexicon", + "wasmparser", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b9daa7c14cd4fa3edbf69de994408d5f4b7b0959ac13fa69d465f6597f810d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-environ" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a990198cee4197423045235bf89d3359e69bd2ea031005f4c2d901125955c949" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli", + "indexmap 1.9.3", + "log", + "object", + "serde", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de48df552cfca1c9b750002d3e07b45772dd033b0b206d5c0968496abf31244" +dependencies = [ + "addr2line", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli", + "log", + "object", + "rustc-demangle", + "serde", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0554b84c15a27d76281d06838aed94e13a77d7bf604bbbaf548aa20eb93846" +dependencies = [ + "once_cell", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aecae978b13f7f67efb23bd827373ace4578f2137ec110bbf6a4a7cde4121bbd" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658cf6f325232b6760e202e5255d823da5e348fdea827eff0a2a22319000b441" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap 1.9.3", + "libc", + "log", + "mach", + "memfd", + "memoffset", + "paste", + "rand 0.8.5", + "rustix 0.36.14", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-jit-debug", + "windows-sys 0.45.0", +] + +[[package]] +name = "wasmtime-types" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser", +] + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a7eb6d82a11e4d0b8e6bda8347169aff4ccd8235d039bba7c47482d977dcf7" + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] diff --git a/examples/parachain-example/Cargo.toml b/examples/parachain-example/Cargo.toml new file mode 100644 index 0000000000..945655df9d --- /dev/null +++ b/examples/parachain-example/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "parachain-example" +version = "0.1.0" +edition = "2021" + +[workspace] +members = ["./metadata"] + +[dependencies] +subxt = { path = "../../subxt" } +futures = { version = "0.3.27", default-features = false, features = ["std"] } +tokio = { version = "1.28", features = ["macros", "time", "rt-multi-thread"] } +metadata = { path = "./metadata" } +sp-core = "21.0.0" +sp-runtime = "24.0.0" +codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +scale-decode = "0.7.0" +scale-encode = "0.3.0" +#pallet-asset-tx-payment = "21.0.0" + +#asset-hub-polkadot-runtime = { git = "https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot" } diff --git a/examples/parachain-example/metadata/Cargo.toml b/examples/parachain-example/metadata/Cargo.toml new file mode 100644 index 0000000000..9276a92afc --- /dev/null +++ b/examples/parachain-example/metadata/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "metadata" +version = "0.1.0" +edition = "2021" + +[dependencies] +subxt = { path = "../../../subxt" } \ No newline at end of file diff --git a/examples/parachain-example/metadata/src/lib.rs b/examples/parachain-example/metadata/src/lib.rs new file mode 100644 index 0000000000..5bb31dae72 --- /dev/null +++ b/examples/parachain-example/metadata/src/lib.rs @@ -0,0 +1,2 @@ +#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] +pub mod statemint {} diff --git a/examples/parachain-example/metadata/statemint_metadata.scale b/examples/parachain-example/metadata/statemint_metadata.scale new file mode 100644 index 0000000000000000000000000000000000000000..2b76506e5d8f0b3246c05c43fca8655eac273b03 GIT binary patch literal 158746 zcmeFa4QOQ7c{hH}=&n8MjFWL9r*bR5y>8@oyRyNYEwAH?mcIB1UUbnkw zMl)B^bVoDF+?m}~a3Fyc5=g*>1QKu{0S6ptAO!~!NWp;w5=bC{6jDebg%%P>AcYiC zXyO0+J?ETz?|kWFW4mwKP&cc&_uTXGoaa2>&vSOecKPj3o=~~*Xm6v^Y=vW$*8X0* zS)8v_nw>`bV)cnLN_ooD{$F-x{>*>k%nkljBfe59i~mz6MpQ04wbd%`h8xj-)DCy! zZyQ_9?C8ZtHN2zq?%_hYUDl&&RF5{AjY^o;rh(EEm1ZOA?1rrrpRZzoQJo%6sXV56LXGBT_saEp*xuMI*UK0@8g1|Ig;Bb# zH-65%(_<>H^INSj9MkTZ(taz9!q%;@ntnL8)oOkqY@{EJZq>`%(YP)w-f6eW7x+V| zG0fs#H9lk(T}?eTrt_WCXJ(Z0bJG^MoxQzgtL;~7(O$V-*_m4nTMPE@^YwBRdEUC7 zP&qx;Xts9C^$G2*D_v~vg{^YC)@-;Z6T9UGfYfa5OA9rTD`4+$hqdjUb~IuB-MDpT z?0I>DUFNE{Hrln_u%L6D_f9Kaz@{{}Hlo@G+#^*`>Yk!1Vu|;tsqE}ttF~Kf*KUOy z0^ZHzF!9X7&Ntuj`vZHG~NY(f6PmpWf>Zb!3v_PMY! zYo1;Nu05mFEP9z!a|iTNNZKnsT3Bs`SIlTxwV)Ty1MfnhUbNWQt~J7oRi&o&IEU%X zJfrSW6LEthH1||~EiBiM&=UA~xxEv%y!2>FRqfOk8@Fn$W@8r!esvGq6;^rJ7I5-# z`tauxR=up2drscsEwsN9;viSE-lARwMoa-CM)!8gQTPL`M_2g=fDp3bs`eI@9&0!E zYL)08v>xN4*8$Si>_XJWn7g$`+wIJhn;5@TdTwk@4!ft;^FjpuooK@z$vxM^5|O@cwDRrIj6C%r{bJ8i?rVRaT3T;_k$GfWt9Pr3Yn9!-XFFjh z^wj6{D?PBigO?lc=i9#i|BouJHtRRb)n*%AcyP#i z)%TUJ{DpXSf1~y1dcLU+o!uj9{A#;aueJ9*^(h@Mzhj=cpi<(khDAdeN7)zV}by{xvyybW7}4CKI&;)^n2c3Y~T=q z&76KloxwsHHEaR;`I^>uY|D;$*3;25>ItRRb6q@j%zQB_XA6WL$99gqrPhdQm9|*|^^eim?wq?B4(%A|gl>FP}$nO}E7Zfgq zx2+`N>G86WNtB*iKYKP7P(TrP=KV%^+qdtfhe|6X(F~^FR|Cth9@>fLUBe{PJ)na< zbO2dox7@l(IE;Z$KoaR4U*|zocc%0>X0?RB)Cq6za>H*nP6^Ee_hbkDPI+$+%&i)D zd$NoERm~4deGcn+ZN|c=d#KtXhv&C^>V8QK8-QQR+`mL9Taaz7tNpM`w@~|BTI7c zYK>ZB8!~J0QWK}%$dc-WnpX7oivEL76_4Sv_`QytFxUMa&sQT1^sam(O2fLZLC~gxVpT!v3TXmo7uK7%R{+)B&MtPr zZqa!;Z)!wMU2WWKG;cSAYy#|K7eqP+#IeB0$go)bJ!;PEt@&`NS+A;l)%2xid+`pA zNmZZ#iDxf64e78P!@m#qIyZ5Zr*aFk0>=24Z`r@Knpvpb0#|4@&h7t2*lH3@+v&v* z+9I8uTBhiFC4|I+c`7x2skvO<=doAnPVU7X=G7~=^b_jw(sSi{4I&&S0{Ds)um+KU zoqOM32LZShzxTIn15k^|-weZsA8{H$^Qzx&`XC{o(AEA9=kcNzRz1Dm3hU+l4WT?6 zoAqYp=0>Blo7d}C`20MDuycHRsk6JuH9<-oHU$!54v2nz{MphvLx&La@WleGFBL z9CzfS7rikvT`Ihu&gL&Q8zByAo|^_!h2ly5P@kIJbuzOMp}dPqua7S_u+7|-Vd8~` zAQpzsW-tcUaQ3X#L~wu!rnJ;xg7KgxJ0P$aLM(qQ}8!PY9_R&3( z&OWVshJswt1ory3cbZW=f@~5@E2lmHisx^3+Q3UtMt|{64O|C0cDcR~?lq%YyLbo2 z42sCWnHm-WiKPR95>^1e-o(lCg{5tUtsLzj&D}n+C))-q?-s@Mz`19{pY*~`?d@QLDNz17=EGF_A3|@3?JuHBsm{O zo)CZ|1(FBHS>65KE4`qL`|SmuZ^a?VEQ3hq+r83!3~51hD-czKv5QgEp{z5I3ckZT zrPrHn9LO4)(P|-I*Baz!kW)xwO9rD#MPHa4`9_(4Rsj!eF~DIdL^YTI94b^%hK-l^ z9vw7ZH9Ty*YPi`q+SoD#+T-o`174|*22(7i!hf}4{yNSczSG<3>#t+`39Jfqoc`W5 zV178ga5DsB>pNu;SOy`$;N2Y^&|6!2c`N0%kBoMEGR7be*4h#5&rrIfJSb3Q`ke8; zSk?pC?gF?T)jA-QI9@2*eKhBcl<1+?hTA3PiKWa->v9!wap0iDz2LAwZ@RrxtL*qCbYRR| z$Rt&1(8&ty;ZPFUNAY^B!R%qWa{M47mEOwz`grbo+M=1VbPs^Bvy)r+LX{dM(RIOh zK}-aLfIR38R8X4RYt@(Zj@4G6&9=5f>E&Wob_w2wH*H70I(SE{>@2gx&f7`8r5p89 zS|Q5!DMavo;?R6DSGBv@?{?_l&(S$pUN1Iob?R`((H2ANaxMM)(|SSNMJY=xeLbuA zZXt|nU<G5a>+tE?C)jRi z9(V2`J#8Do_7BrwUQgLK7x@$C;wg>RzHKD-rPw0v!|WD<7?r_VDVoMIxe>+Ob(~}mHHY-u z+Lc!ohJWq+ibzV~ov_lOxZAuLT?K) z0IN9MkdyJ&(cI@WVHg$mLc3EyOZo*`_K#o;8u3M?qj;j!1_v`cN2+j%{A zg@(>98>car7h&a!`!a`ukqz(fkS-;5xD(zFF-O8Hyi*BjsSv~l?!%Z|g>aBeT>>Ov zW2tV3?es*~AgRO z-8!7(419@S!pGqLz5tIU41VkGH|Q9cR@iC-k3zT{QvRZQ)GS`n((W45-yp&RzPbR5 z8zU^%jn8wvDF!P5RT`+1Y8H*0H9&k5h%ay*fgOP+iVNdyYJE}ACR!=qac2WoYdCbS zfh{^COWG51znYN2xJLDMMWYf7aWcj`Vs8q(akX83G!H^-leAC?GndI1k11*Re21#2cMV;=y_1VnY@Pp1>>YB*AXM~ZZ)$i z(NZyVeoswZLX_7^EdmLs>>!?L`8h*UE;i^(#>a&ELu%EI{d}`iuky@^Z|3(^5rbfn z1~>jd&A`XfsKBak)}+Q2e2oi;o>3300_Tm9SHiaXKWYMyzG*)DLrkKH$R}tEBxcGd zz)Uy5sYhh#)8Cv0AWO4Q-`zQ#w+AqSULor9B%`fyfXW_=1Qj8xR#`8DWGtA>(XNf14{< zCXW-;&!nzT%)=DEyN46wsW0nQG&*~h)`qBk_Uz?O8-Ry?lzVki_z$%Q=o@82Nvw@u z=tkM~5~%6xe@Rm>zx1!)K)h0;ol~#rX$himIIRXe`LP}c2xkkE)P}Cl3$;p*K^h#W zkFtC5(H4D3eGcV|G2Og=W9e!m6nqP-IQe@Fz{(C7uc*hL?S!p;04y{5f|kE&a*+@4 zhw@>97IOM357fiB`BxlQ)Pv$!BXH25mYLcFX%>st7Ca!$Q`%s^tT69cd=e zYQQ7WO7&3mVdLoe5>L=w*{^osBBSLpo*Hz%*50NafF#;<%=k9Q2OYqu8p8;-c0=

1dH?Er$qQQgntgvKyXCp9A@&GOYq{zflEVg)4z4V_b%By2dw#Lr{A<->ykbn8G9;RX)m+z{jf)x{ zYkI1^eBUk(p0fd%%v>aMncL7gp^sO^SL)(a0A{W{mdU!}TLeKld2{S&cn zzpdmo>eYEoJcqq4wca$kxyMc#035f00yqm0 zWk4Hw^^mr>FbteUn7V0H zv9kdkDBnp2G2;W|%Le2NHlkIi{Q;c_M2-6ZJUMr=krvf&Fr z>=o^3TeL&M%E^#d$^nAJ#sIyhMI~}?@a{?BEY)&j8~*i9goDB1iAZp&Q+?fkL5r4= z@J1IMQf)O60SE^J!p=w!x2fP!b_LIcMufBixaT3jVS$K#*~BFF(MHG+y({Al(MFFX zJgkGWBaSU~Ztlx{+l9Lva5i8mARbzOVW4~=bU-kpC`Hs7u!NkN(l(^OUv7L>>s5<> zVO5T(=unY*Tkfl3$`BiAl!~QEb_~o(-qNJL7pNT!kCVGYfr>$YU?sG#MwrmL9RfCB zY=sb8kv;n7lh=im;IDp)U_nMb*h%F^AJtaz#%_pxq#|8*(|srA#&jf>rwyTnU5&Eu zPu7756@+(?jNlP9Fp7=^L^w6J~~(Avrhk(#-mSr$$~DV;&Ahdj|-=y#oY!9YIx1 zP{UfK8%RR!kX=ILPGfYS>R6pSpv5j@)b$&yhEuN7mfwalQYE)Mj0>cVW^ad7Id9D% zZV;;!>=2>j_1cYPC{m?WlZYqbnD$`$&D-{{0S!eUc+qVk&o_uwA_ssh)Ue;&H8*6@ zo~w%spwS{uT)$CGuWhA<&^Czz!~(PGV_ILcduh+fvNM0A5AHkOwAH-^{?7?nImfMo z2;Jq#A(q)nOh2|DQQspq2(B%@@KZLc?q!AgAwnFaYI8#x=@)BuOjN*4IjlMhg z`e13aLQ^}i+Dtz!kRBwDzJ<<~FZVcG#+?~h=X~0ynbVavWh+%M27128rfgK|6+J3; z7WiV!A71hZ{^!@+K-0UFnB6w?8j2Ch3_CYYcVzQXjPM8T>8pC;|JsBG z?qTY+p2#l&br3?3y>{ADU)R3-6tl}-JCp5t)b%5S_fO=y9u5C7g2vPN;qQmP@$lu7 zqr=}H@y!Wz^WL!|Ha=prd(h|qH-5y%chl@%3^3#0&6juc4f1}z?vTZI$dbZ`!UX-k zLaIIWx^<)|m&ebV1;EKh*uLFt-TbCru;!vm=E21(+!xszqCJw52FMkfw*?Pq4Sw(R zVc#3aZo#5~cw>BS+1ojF|RcaUlUpXbDCy@M{1RErO4)gS7y zbImG!EIN;4-2RdF`5ORk!yh{P=XF>j>P(W89C=TDTTjG*gkMy>j>P}G`er%=>DzrF zNZ*zaq;L1_X{sw-m^io3RYf%<$)@Lz$_eN8FJLPXry(&X%xFTMk#%0`f_VseW+(j_ z62@I>GyKV8@9RY6-7_}iJ=LL?;<^aloU*TA5a-nKkQp@4C_K3-tacsj;}NuwVSL1 zu%O2!fp7W->9O5%i`^M!4l=@o?%NS~jKj)K13npgzl+PXIMyL>;oS*^bAm{E+ z4$<;k*tZbdJ~Llsq@g6?&~choNbo>xZ>P1-ssE^NstFqC(b4Cc2xySmh6Ft#x=hNH zogQF)0SA&IUsmTD&0Y6=v>GPAGHPMIy^Jy2$cCaP_~7OvYH0;Q8FDywL2xQ?iKQ1(@IrM&Qg;ms-1f3`qpuHNrZQo*P!l zz!GQ>3R@1l=Ll%4;z%_V_hO1KD&@U$1!UGfyjLx=XWK0pMkr2wJppfRZI6{~Y(o_H zNHsiM5-kx)4$d3cw6(k-ZyTp4NIUv9VsL)iDGr(Hw*{_p4>w)j*sX z+~d(O=k015aT;RNm1!cKjUiJ*y1ZR(w0qHg9J^UVMV*UU=Qo?px_XC#!$meDw9|DI zBF6H;-H+qI($Ie>y5|)fV`c@|cX3k4e6Fr_T6>6rM|{#O zvI0dlS%Sf#PVV?)Jpr0-Pw9iIhz3Y{1~S*~^t^mG66=ZfMz#4p{(?r=jiS9KnIs^Ftyz9TgnnNk2F4nqA08VkBNvbWUG(KSqI~{Pt(u08^qRa3 zPd%#j%nEH&((*hb(R@`D3SolAvbwk{)fqM#2pLP&Q#um9J>u44IzzEAkoNG7qkH+@ zK8KA}tT5wvW4HWQ3DKN|6trQV*I>W0o&J$pH3y@2se@0%d(^VvSa)kRp=Kf0(GXUy zyM0J&vX7D$@%XKnjPhKprgVwbx|p(n4JFdOEb@;{oSa4U(K1#TLvtzHx@xsX@t6x7IitsJ@C>sxEUEv9`d zMez=#Zh8t898iX#DMHHdQ~9`3KXpQQK@2Ve!Y*$mWZ9pa5@-o=g%JC52(iCZzZ~#& zng~;?tW|%d$7PGD@Z~^sf31tCO0iwrlsZdF{c1oj$ro8zn3xkt3sWCxl=9~#%fAAN zwp$fbzaG$S*T6dKn|ZLJi&JzJtG2Le2Ij}-|EY~5+G)yAl+=F?=()GmnA8Z_V%Z8P zF;2H~qi7U)YPHJy(_K0kbVhkP<0-AJYBob{eOw-&ey^uaARtdvw$tyufvqtwo;cIJ z_!H25G0hPeHK25z;Gf9I!Jj9!(>mgy8I*O(Ut&x%bY9sdsKULhN})iLXo5}1rHsKk zfPiNd3fY-V0R)`Rzy%z(&Yrc8u#}=9uo1;MPd%vhr_V7EIz)a!1y$QvERnB@2w6Y{ zH2##P&tS1Au43vCx=9S+30V65I&B$vK=+vj9soe_AOG>P`ByNB-14TG1PW4ONYU3K zWCY2?Hg1KLLNZCzanKKGZ;e{sBdH2@55=%8B+CF$2XT^zwf<1jBdY$TmU{`@YdLH@ z1MxM*&yM!RXcylZ1>cFe4Jz_6gxc~R_3*LRoHa|HPHOf&0sv+n(qPRFt9m)K&bfpa zo&n4IC$;`~|Ki==N+Yv=HM5Rj8OFI*kNGJq$&+uu0#9{e(rbN)^qSz&X}A0{U0Pv& z?2@sMC zyO&AfNa##%BL=8WD9V`T@qMIpuuM5nu~$#)0Tgh60+#h*4WbeWLfS)Al*&I3>!61i zD?P)%686HwIX`HGzIOTCyil%D{BwD0AhTK2dY0X%IgUnotvW1>h%%+k#GVP-RN0Mv zo*Trv2KLrvm%=VC4w`%aBogj}!;xk>T>nMf_}qq(ShK6-p^|@HXHwMRYdbhi{9)iIDU^p z9I6N=F086I7S)O-;MohYXtL}ARjqLH8s0hKBz_0+KiGtCdJ=% zknOT@AUQJ*#K~m8=^DimaH0L$bac>L)w7(JMCuJNAjg2U06GvS`}^n|r-N}B7TTQ_LOhW4ku2q)a@M#u z;zGZ<;Umr==n$y@aPRfIYiF$=v)cD+#QWts(8stGd{I0kh7K;Ss#H&?_SG$AvKyTJ zEG3&RRNyKq95h8L%VsE3SY%Kch2eAcyoYq(Q9!(B(yNIm#r%>i5FUj7(?KNvXRN`g6t16`^49YX^77OhN`zOGi;K&3j3b*^HnZjS*!J@6Y2XW$W6n`elMr^n#QgsJ&6 zFb_G~pt1X+*!{J6lRQl#<2DR*<}GAjpMh!6Oo#IJXIa#`3c2O-O;3Fmk{RkFU@tud z+dqEsiKo=(bzC8Mm(i`raP2~VTJ~^l5duNPZi3ec!9eyKOUR?1d~e}f-*wXWW`f}+ zQfC>02*Zw+7%ir}kDE&i+;^$CXyU+TxZP<4#)^lr;p)b~<$C_0IZQA|aS!2X?JsCu zU3WibS+JPCGgI>$w(R3h7AI;x{-$rD2;nwxLC`dE#v{~~KtbkY?oMtR{qLFkaMaCs zFCV-tC$j|$4hK-`r2+!PqPqnou=4Lg*zl(9#EAE~gQsjK_12!hFKFEO1k6T#K8MZ| zG5UGM6!PgjypUr%Qm-bj({FH%fjIeHU6e2C+?4GTsDEd_|8R~@BP{TajXZ&de*lqE z-q+`uRC@PuRv zgv@dsh0&B=1$`{oBR>6J1SS6%lf*zs_>ppU!d0ZO1*@VmO9#iR zfg)~pC1ei57+>n{7V-CpmJq?pw3N!p6Z6Qoh6e`;6FQIn>V4}OmDYWa69P7+ryT(^ zMKLqpPmnyzL~eF0b({%bE6O3+XBUacKB~k5IWQ~9zuM}sjzEBGxUd~kzz;;NiXu5-M$L@;m>Qx?(7c%H6l+@2MkWnZt92IVwTdVAf-5iDVfX_QwH!YosNggaom0a za?CxoLaW%Mx(fb=bkvrB?s7aeE$f+T?*l-2@rN z{>l&xXc(7+G60KA}!rnst^#rtbGzK-b zn)|Zgu)NDi*zJQBJSO1jCkdlvhO+l=rXFX7d|Z3b`@-|~s4pWi9VjR?s*TYZ+|S{I zDZx}bne0&L58mn%C@xHGmB=3V7}t9qwv&Sx$35O1129YbODy***oZ{5uDZ|1>Gj^B zy&~-qRiuNWoSh3Y1mx4fsF(FVl5A$G$ZdLhrXvLFqt~Gwojj-`JEH~bmX8puY|v#m zN-kMW8EwS4wu;k?KqfBPmNWrL{*FT%oyWZ)% z&3h#t#ZZNKE&cNmn3xm>oAx^t);aI{a?`Wi0K<0hPJvd zP;@NX-`#B1(;jA4pJ8yfOJ1C);ifb>4sqztVJ5k3%nA(kEct8Ssk%*IGg9V4)vGO$hKo6#}8vTlV*tfQK zdcPzpTJ6|C&Jj@ejiI8kVniXjBm}z@#P`ww><-Su(doF8>k9EX8tmVdJ*}}Ich!Or zSO;OE24rZa%_CU^DK2f)^y76Rb~W6AQfdQASZRs2)Of$})_}1D%0|Lq;<+vF8+zVH zyX}+P% zYyu(gO3JOz`=z8ydmfBR8T1hALxvu51iX(77@?bDr}@gkgJi&7`sYi;Ho~L5$plV| zWKDy>l&7^7${gTF!zm#*c={vWI?o)N8`umK%a1?Wkp*@SH<)%!Aa&#ux%~JO7`)sQ za!E{Txhc>ZK@b)7j|^|@9@6*bNbIE})Gluu&z!_()rq_22 z>?BhiIuZ8Z4o?p2(9W<&t2nqbJwbXWgsGQJ+&4(UD6Xf~r$hRFgS4o(9jrwS5K|7B z*O8CsaPFV8+|ry}vVd;7VGQX#_G#fyhX0Ga;LaMj#5BH7SY*H4LZfd?iGL%KGki_= zXCI;j&@IxWrsc#cDWzl8cf)fNC{RcUcVF#8_AVKS9Nfu43m4J8M;JJGsc#oQQ`ZQ0 zB^sTpa_&`PU8+=ew{dsP<1W7Vi%R zQr>&bEh-U8x}^N>keF%Vf?2%N`}84jv11_%xeAXK zZmX1QUJgEdb4i)!4dQ?F4R|XV_#6uW&!~4Db>u0OT{prl(DBf{Kwv(SA!XE;;(8;g zVKw6_zom7(A6-$w!{O>E9DJSdJ6gBjbCTeMT#gCPfL^fW)lI>jL4nntERHz+}%m-Ka; z@``Or4mgX$yxV&{?w{1w4j?Dk={ZhCH@aqUE$IQVAxI{{HO;`ALyv|ebRa7W&8>0j z_q)=!oYOp$7@wosYlC^$NZ-=fAX4Y#v#N3-ii|02ld0?ItM z!#WG-S2s30xc>TkNs=%iW({Zr*O>QlDr3@>=&Nq7WVAIKAQ{ZXLs&1%p|I(n??c|p z$w=IR^awJvbDv101P&4IAsW3Ko;?&UD7gSltk1-(M+HW`!rSkA%V6aIB!WJmH*d;> z-b&T;?*~UMACOGfAFTWh_-HbD^{qFctM9x4eSEJg4Gd1xp6j0x?STpZ0Qb0WwGjBd z5$ywqcSl!olwdu|&A`l4htHToLc~;H=WkY1av^Q)1LB!QA1G+a0t|Kc1ZiylKu}Dn zf8;;^q!s>S&SGBubI)kkmQmy8iYc3KFYJ_p8Ss5i;a1TKk{Bf^^L4$<+9MTGAl#o) zY0o14oYGC^Ria?HNZ^M?UK6}=7YGfRx{uMJgkx@T`uROh4YhTFISu1fYK7t^2 z%dMN@Bj+C}3#iKPtk6pv@jeh-91Ri&E0bxD%R=7s9(e2+taS&aO#D-R>2l%pWN8M6 zoR^jF;ffR7@`Z3D`PY?X@_r49B*!y}c9RCq3H*GxNt@6vYg~toTeViRLC?&ez_^4? z0~BCvgIF`0JI{Yo)6L|oao;e?TF8JbR>R)ep4Kwm^ZuXuYm?CI<$8H_k)>N?}9#V)^p%mikzmce2#4)@rizccy$UwkTpb(K>n_`!x_q+ zOA`XaeicmJ#C`TjA9=_w(Z6f$+b*7g%eMVKUU{GT9D4L_+(A(~K*jZ~+8u;@m_Md< z4&(ExuFfWVv+XO}J%upo(MSh;vd}(@zUk110 zu~WF`xoNR^V zQ}}%^1%M&PQSdZG1r=XD4{(Vt5^35vuRtHv7r#};jo_%Vid@z>63<))LGVHQV}X0d zV!)CNOD%qfjt~aFAW{1_t?(a++Vr&gcRrX_|ItfZB;YujlAsWtcs5FR%{U^g}y zXEve7%nML5M7{Pu#QZkIv-4kCe`GamE!Y526l#eg8$TW4x%@`5;(sANz|uEU#5`Wz zT<_N)cUmKdSC1jv8g3n((G27(##Kk-N0?dzT4b}eZ`vrG>7k-#rM>e}%%qpa#=uK0 zc$y22U!2J387pQQh>*CmMVogm4|)p}lL|rA0WU%7)5-J`eY|f%c;Csv>oCDqNajYV zKy0zjVIKEq^m;D@4G&WHXO0E)d;;=(AH>a*1mN;pJ&?&3z}w7miDoTpTiCR?17?|r zjk@Z1%INJDD3$%C9yA|YMml3ZwmBb4`Q1Epx|?spDgZh!rD?!mdtWY~yghCu!!dV! z+LEen<{dwjzU)NY!+d$K7Cn?f(k%W3-Bfy6>`bOcUT?qCplqm9WBWknH10}L4`saE z`Q~jR^urkh(%^rT{7>eQjKY67r5fRMkM{1i38b<4{lxt-ck$gCL=Pszq4>lDdYzOH zKZNk(MN-?o=O(R9l+6rbLnAc=#bcpY$8}f9H-&^IoH*FwFm@v@;mV3=y@~R(*h$J? zSzh7+S)*$}yKZLnpvb-t`qV@a0ck8`Bl!??>v)rBn=t8hTzUt%SDY|rr=>EvpPL38 zgr^lvWFbzRa8nYt*1JMf?pQ?Z9V0$4SF(c=3qrd6quYx!Z%QfVQa5Ure8#pT@B;T8 zHIR>AM(i==E3t8?5$`|OI;g7$=48n##0VfX zQQ~FJW6`Fl8}i*xc;83wj=640tv51F_9Y#09fUGCPu1lCAik}Rh-`q#X>n^JrQ0jH zCNsI^y4E{Hd+uHrnI*NwT?7`yYbx_v%?nc^&<%x)8s$A)wbQ<4(r0jVXmk$O>|?Ulsp{_gH+J7& zk^P&}5SsY8C?#jlE-`f8?UqBQ4M`A^t@$SugES?~ph!(BJ%ffZIJSs_MXeg{Z?UH99>`g4$jYJ^purT2x4scvt1}U)rX-| zf}mH2F0L9c4#hViq;4VR+1!4jP!~g_B&uFr(^=wTcx*RF%DP@%wT{yT)OI3em(WpWh$oMzck=Il!A>tim706a*4U??4vs<;)#-S3D}1=t>21?6y}b* zRPIr~t2g+)G@vb9QH)^jijr3^WU`-(k6cU}lbc2nQ%-8%XfN0lHB{y6&^n5U zNgUfLJ#mHI%1Kf;+`(Qc?`6IB=~uny^a~U=%D`XwpG=rh_>ahp7d4{yZbt29vZa_p zBZxi(X>s?PE?@4nVd-kfk+O5}aOtUj6%yS&N z8CUYlRJl|8N9=`FfdA}Mz;+bzqT3mABQ^0MYT)FxPO3_}FuWXfcjOAD_3>&r`mLD7%DPTZmREVsw1q^k3X-Cr7|2 z-2>L_8h*siPF$eCE77Zw%w!Dkuu=u3s8emiGSjF!nqZGLDlyr=ruFnyAr}?{!A_lA z|AEk*#$#ef#xHA!Vvvv;Zbf1ZNE>b>+Y6GOHBnok(%dQIBuuM~i}4>fmyOYU&RwJUj-1Ldpz)7rrSLR_l zH}}Wl$}B-?!6KXC9Hs3uK`Cqiw>R97a6i}y4Y0G}4k<`6V$0!zA$B5?b36144#=B8 z{nq}ZGxKpn(%VL>2p1wbHpz$q3O-#lC&WDzNfR=&xh)vg0z12Opqat{#8%*BSkaNYG%kD6D8?&r~lg`0aWC-}@l>?1wYz z!w2x$YlA1ypKdo!l>l|ndn5@MfTHbbJ=?PY6fzkg6nu$7&*+`Hp zVP^1;;sn7d!g%LxM>IkAX zaKec4ZDzqi7_l>8E{L#eHqX_zRVKTr*GY2dPzFyK)Yvi6JsKfEVn7eTO;8pF*VID2 zw>Lz`ldMIvq%a&EEkRa;o#$eqmRdFF()=x0G-zgq`Ql-jfD=LOEsS~{Z^clUNAB@nLSGa?V-y+0aHg&{9H+rY_j+IFHX2V*-?t60_g;qO zeMR4Q^5n_$5X<0(`O8>%lU)AjMq#Jj-iyvY{&=-ni2{}#hsCQM2DRqnWJ#y^`0>pS z3Nt<~hMVY=`S9^c_UarN#;_Rh(PuNcIh(M@oO3AmyL)|dv6q9e0y}e~dAlG{xGRv| zXq=c`@0EPnNq}mGiENO_Ccm-F`$Lg=amAi>$OxOpE;Rnc0@95j!RzG4G8<#5jF;yp zGwQoco%Sx?YAj9|8vUBtauy4+ZIyM-MnA*CND1gS4#oimQz$ugX#r(;JP z4e;W1N*?WYV6uVT%}4ATten;%JQ?7UTS%Fxp(=jWgR;v(+K;T5wC zFNqU#Tx0l6DGZ`)-WTCjxMKcP>WjlhjGLfd8%m>tapzZRQ3Yy{RA~kG{1Q3o7c%Pa z2E*Wh7?H2orGG88^sfw?2txS8p+#nqU9dlrrDE}JiGYU`jm4w>c7s5ozQ!edC8PfS z*h~0^UBb6gOZdjHCHNPs^KzQAG-G_WZ^EBNRcqQZ`ZrB|i!=O2Mt!Hh?=-!1Db5qC z;w6G*enTW}BodZ+v6o!#@x6>*jpMGCo6Vb@J(Gp6P2k}7B^TNv7cQ3i;kpYC7C(Kx z2IYm<8iu%t+MuH-uHYwB9Ie4WK-uHcph+NpLR|jVW>LC;e(YFqco=Po8acayf(biM z$cqqy2b?NpUP2pnt_4uI%@D30uzf2@5&v;_v<>-0P90L;M(Ybq$rE!zz=dq)!Tm$`a8A#X(P&majJvQ5%zfh4`gA5rh4 zF!^(5sUf&fdIB&rVwmj;+uS77)}U`yrzpH8_N%$Rp>mwDlmq%;l(_FbHeOt!2S ztpN?t7>w<_jhB(1f)kc8J6LkTg5&~JnV>`J1;m-sFc!1@!1#T6qHl)b9*#9m#a$if zk+B!_T51RXa`41&h=tB*{!%^))i)SmgoRi`gM+R)&^Z1jhU=sk8qy*%Nx*5kPJfi3@Eq_L;=RI64@+d5N@XV)%lVkRpT8&Oq5^QNeM-oyKk;_}ffH z1$MvTj#5O^ACAHKW57i%AMyKqigppqmKX55oC(ewZZU=G{ zi`QTSjbd;^yD2bVREQc{x~XF#aCkfGlpsXvttGZJJ%Q#BE6{~ShT@{;=Ht%zoi->O zUSQoIiO^QXlH}TP$T&=ji|lbU!+~3L;^myB^mr1sD?t#b*9Vatq5YVqP!x9v4cQLV z=MWRe1hx{%4q1S`Of5!RyCJ~~j0Q{r@T@-{n^CcpD$T1%IgO3uUB?S74kk?__gY1O z{EYUn745sR0A(af6WJ`#sBPooYDmSRL6Zhs7HPft7#P&TLb|X8SvfDrkmtps56iJQ5#&Vf%e?MdIxw+An=vTm)C?9y!T-9=-<>1{egQg2eWy>HuP(8veXjD1ltpciu zIrj8aOj6xiq#YutWpjVKW~JQ2WwB#QNpEDt=Jzr=#?M(_$COlFLpduPxM)i1)uDz1 ze`F`-4Yh&t65muT1vjC~=uxOH9-R3}Bj}2*s`w8O7vMf-O);vESIW1$qFHb?tsSWM z<|EuwYu}ui^3-=zR~}=)A3!s@2elagVW?(g%(YH6Dj=0hY^{#EDDP$a#Iaf6e$(Fp zgW@3&@(g1mO2@7*i|T{;^(#rZ3~tsyRYOaLjc&vMcL2-<)W8yJM-Hr{ zY_IL|yqDH3qkDX>yl*P8H9PgH@D|r$a9!pBUSuJ+W{sY(d46{uJ}qO+j+}$2T&Mj9 z5&E3HIqFm@;_iwIcx_<_Q|HIeCD+2bHpa#TK%SCLf?3$AQ4EYbL5(GXvGc2!?kJNz!Kl<&CqrC`eTz#A+hmGwTFe7?g+>93?sDVVXJP-p!B#yp8!$9PO? zYIvCb%(g29Z?#?Z9}#qmBaJZb_6{WCTBV2xdf296AP5QfatnWVJ^2Mn4Dce?aUr-3>r9Uw zO$HyNafZ>hjCO{!fU|8n68nk?JWYBAr(vz~WUly&BnJGMR2RcTwXt3tiT4VF&mt-W z6LgieAq<6xwu5jNg)#(mhs3UqLdV7ybsI`FNVo_)yNE7Ijc7-J)!abH&No=%rdViI z_HiRe169ayTW_O^fI3T@UCqinZb#zwPy{HWLM&O{^05y`I*H`Qt z1FEv+9%83*8;G@86s6LaXab_Q6v~s3&J0oI>K@i^ERZ=I(ujg1lVilZP}rO#Y(-NA zI4oJDQ0JG}-* zr|qAn@OT0Ks$JB?0dhiWVakpD1seqFSI*5FjE?(9%y}J_zLrFsTWn_ySUVqjTa&gY zyz8#5U~STF)vhm%x)H>TYw;4hsM)feM!Gqqix*w*?%aVwrJG#8)I=s?6L;AsQRU4R z%=uaG(@s33%NE25$w{`I^A1C!xwvo*VjM$6n=LHNQ3$wkPkJAX-=GX9w{Ry6 z72@7v&+UJZ=lxek;XlMrC_RGz2GoDW_1d!E$k;=67bs~N(Yq%`^fzbc@dxR_gxsMF zWuKv*>&+`B+ZEZhtDVhyt@6y-v*r&ZsE*_pAk@GU51BmbM2PKbmB+*CnJ1q-{ZtX! z+=l&o%zfdhlOqVhHZ78lPL4=OJL65==c!LnzD(|7ed5dwTsu0#RRJURvT!n21EFiEhX z?8V=vN-(RI&@k5A3Wl;Cje?^?*^OA-?B)g23mt@diCYo}2AsQ^Fd&!@>^q8-!PuoH znnd8>ub^{0!BK%|onmU@E)wi<-A{ly8X*@v{UMF-Nq!{a%{FmdjczU2^_w6~z)l38 zh}F>|v*VjGYT&iIbHChSHOgP`@W{ZJj055kPKl0Gt$=%kN;0c1{$s7FV#OI^$- zsyEwFehvRi>hID?C)xbeh&nZrt;X3EB*^UzT-v&4a!%H5SR;aCnM|~Rda$)R*dyJP zV%C3EkD1s`R2r0or_&=E*dP%mlIVntBt%O^h*3slsHrCV6bMHZlGgKjWeTt6)gtF~ zaYS7_XmQtEVo5Ljaj{73_UYS#l@UGdKD2u<*0vu^`O3HP4bS!FfxFK>0t{Hp}3nH?Hy=@GO7@)tRlfFB~^twsQX1s#fLt)del=oAK?mKcWmOd8zZ^lC#z4)nt(pvx`pCI8_5k{S$jjspc}}h>~tk%KbfVP{>Yl?2gJ@@!j$wV z7yPN$``kf$Ac}s;-dn>!VblBNR&Bf1Chw*_ikXlHcx275bKt|qg)NVG+t{89>7xJfz^ zy+ui#yqEG`DfzJE+_4yDFIco4;~)?03~C&;7-;EWV(^JVXpmfI@y#TXi%bI^8F*=e zlkD<&x$}jiN)1A)(|))hs;x;rAk zQ5J(!$vAqMIdtghRg zXz&L#(8^j4aaQd~?4DL;^s86ogdTBH0d9PUrb&+@5JmWPERs7R-&k2>r^$#InrhUI zTH|q6pAnV>SD-Mm=s0UAnWD-Y4#Y7HF-A~Ji$+F2qXolQv%#o8iNt3r0bxRx7s5az z-fAZnTNITYaBfU%85Cop=s7r9Fg>=L*X%^N)*ADpK#dyPgPgo(SFT93(oeBxFxdia z7OWi+A{x9c^ih_2h%N%A4Z)QrrF9E{ZerWDdT;boZ_w(?TTJ@0&U`2yG+|M}+3K{g z-WHq$B255yS$~JAHnLFJI|`!HLnoIX(=y0JH557hnYM;L0M> z(ajLM1D`tdRKvfq-g5ir76fkRg;qiwXu@#F>IMda_$ZFMx7$gLwLcOdjU>N14vcz% z5ko0HAeK8CC?!1Vp8UmLK-t)FoDh>UM(xfr2SeFogh0H%XcHuRY~}Fb4P9FA3QBtx z0W3Ge(o-@*@A~c?UF=;Sj+5C^vkvZhVy(6d6)!(;EH%^vf(9e!Ef|6?=y~I}aEc_s zUx%Ruw4;m?8#LdOK}i-rI4E>WYScL40P1Pr2;(L>F5_l^RBq7NW{yC8#-h^dd@zy- zTR$=>83?gb@DU5p;WAY(RI{U#2~=ez4nhg?xJ7|pBr=*q5jiJN_bD0%@7F7ikd!x@ z63hY{g8hCQN*(ir2rj&{!jL_uFzQNAE^NmNJ4{ig@>zpX;V=k3Lh<0p5F8F7xNG0Q zdRXNn$g5pizpFU21`Y(Fx1JQ3Ax{!n!=BCn4k;>1Ml66aeipx_ffXsn%zGN*-5c1K z%fS+U30D16#I=%|+mX0{?4RBuqSx-C69h)zfjW9E7?M_qdtp z2_rO7#K6T#1~uMtXLvZ0D_DmxHr=WSMKI^qJ{7r6)RR-FbK|Rq`=jVT=)oR5V`1xK zS`WS2eA!fmg^XI+p^A?>D6QIvzGF*aJm-{JiKan{hQ$9N!xI%cSWOlnt8MM?j_5i2 zL7_8K^gA;wATrKySx8zvNtZ}|vb{orlUxtf$1}Tr&_pM2DGmMlx57kQRinrPsqW)` z9kbRb?2IrPPAW@=umceQQgf*<^%JUhZ6sYv3}g4!(fk-p1^92btKIuY`r5r88Xns5 zA1|BDs?La9CqHl^h&k}oK5QbqNj{!n2C)cFz~qnH5_yY!{2V>*kK}UL`|PbVe*9SH z^OtaeFRTpq$~h0gc)DmJp5*p8%x8AdN&WZ^jKNbM9MP-sHa&5s=!+tSt;(oz3p5r3 zok6l<*kTC^fuq7CKG+3<5BG!M!v+NW2L_eD9#MZilDE?yLzErTHVvUrddKH^+=5jf z(}$BSPSO(7OzA2V1_blT<}o_Pp&aH|jo+;!CStGIYR4}}l)0YNJ-9&VcxtB$Yk_Vs zLs|aaiV05cPOMxinkIq0&BY}uV&o*7Fc;JR1c^*4D`IElwyEY?^H9G zET;om30YB*dY582k;GC(I9+N~4_Rs%cd=cW~DE?f`^bwZ4d@0?GyYfSDeVJzd5$`^HbLP`I(gU^Hb9E z$50RJGx#fmpPwB>OxNvtR%)osK|=%R>Ncvh<*%D3;hNhEw{V#D>?`{OixM)1_#(9` zKlaa?)Yx_A6SpHzeICBNn4(Hy7aqDD+s}NXYCgMMui8&|=sw?d=%)L~&a_aSF9_W7 z>Wd@zPw38^ofogI1_CoJ%M6vcgMznuUHKDS_%WcLdaytfLmX~Um5)T z`$5Z1!kUVCiYYc27z;wF`a6zSh1D)vLiT2bf^UrI^{$3EB(sG{77bIg2-*-zg*X~) z1r{jDI*0aM+)Tm<4{bbV`hHgHYS%nc>;Ti9K`^$Nh1BSG2Gd!TL9}x;A=aj|M486k z!N&%bnkETY@>n7nfk%#5nKyxYR)d%zZ{I}RS;uC&otP~kZSA52RMNYQ78~Tu*d;_^ zGWiU8N?D5}hlHuF$s;3n9a5PU;l$u6W(%}}`eR}Yp!pa8$- zi9xV{$w#y-LT$pQAkR?DVq1btDNvIX(2bA+gUO0b$E}q2Br*vKm5Yz121<#sU6i`*k%F|#LR5qs`E-^4#8&8Bqiv=o6G@VWU`s)TfX7krG9Phlt4fEeJs}vTnDF)hEsXB_xdbOB~%o)+Q&&x#AoF z7q03Ckx9$>H$h$u2f z%w4#QkSPUIr$kVfU@f%vXq(v2uv?p8#X3W_UKple`8RE-2o@K26Q(F0G3g2v?FBv5 z_-K7pu@%WqT!PRH-*OAEA?Jv*j7MB|Rm&vU7c->%6ez5Pb^gJ7lN+C41Zg9$jl58% zC`GIv1Ic`h!6<-9JP`vwRy}khr@E={e-}MiP(mU4GXbRe_%VuqkCBzZn~?tArJli3 z;c7s`D&u5<*YpyRt5MY=7Qiy z_|B~j0?;}bT6$74Wgtj=uXF|1Xu;R=0I5i7&GyqeW{sf0?#Y>TC!=74#3m30Rj@+@ z1=!-(jLmTn_cU|wVUTjO}=fPb@8WMZt#*usX0){l?(B7bpFSsVRBLQMXJL#IfE4bfm~9Y|q^=CG;@y zIR{Y)k%Z*k!%#vtj{-vm652W&P`AJ6IrPdphUC~>BRhg zL4#0QYXrzJ^kMUSLy!WQ<)G6hjwvb2kR${dqldF0h(!RBgBTCMPFuC;=I?A8&M@-d zY}5E3rdvqxTo7ejIVo56uavMOtqcFJc=wOdE z^|y@vom}{>w6*?@lo@-bvs{vh6HR|-o|XG2{+F6(-vlx@=X4N;T2fE-aD$giTeyge zu2}J2-IxCrH8&t3IW>nQ18IJS~!P9{GffWN0j+aqWQ1G1*-8Lo5P5m}(Qr8IZ`F#hyWWG0| zz8CjYM7G%EJA?qs_Q4cXyg_R=}w%f{rzZ0o&X8Pxx?_pBG$u~juEnv!##*% z#MxlN-DzBwWNbR`gPBq3Yxa5rYZpYt_zl`N>^gDFDJ+RkYQ3}2M22s;XiOnp7=Ta` zx%K4|lFcEtBS-2oPBS%J*m&YBsn-FxCs2H3jy6c^N0!Te+>5RYknF>I)iSHe+iu|< zgEa-1kjnhA4YO(~)$n{BccV47bGY$O0y^PYb)(pvE%!4?A+k?Ss-oPCZa{>nmg$8s zf|bXH&3LM&H8R2wXo}q1?!A1QLe*PFtw@Z~5DXi(e+WvuL#0=+)9!`cgPfYOhd@v* z#*H5!1TArRo4eVpf!ZLCTjaqgc)wb<-KQ~-K@Z|*Jn|^RR@RG|Z&#>dWQ-KD9t0n- z=K0`pQ2tmBc<-@#hq`VqYHlM;Lx_c=Du;jv9ZK^f9HG3Lb7MIAa!BV#1;GPqN=S~4 zNy-lh|sXL zPHV5;i4Zw83)U80-hJfdhc}`)Y~7YSsv7yHS6D%4Tu& zUtt%ahbWQV(4(u_j4)48X@ulobDe+^bG$>ZwxLXA2dW?yR4M@Mm4wj zdj0a2)YdMe+_pfGJT8a*`$q(4v40clRI8%~8pApNanJz$4YR%rkwUyr5r*aXC;IrO zL;nL2)M!(I{&c7MvH&Yd@aKn1Yr@NFyxr!5aGrE@=85j13&wqEk^9kX?5|50? zW%VB;OxxitYq9xY)<)jo9r*5lji~>MzwP3?rVsskuX*98-AN+DtqVO3wHj(%=xNz& zTNonF$F_x&dWdZy2`JLz6ibmua0=R{4Q3EoaM}8@pBZj}=$Ty?OMdOR_J`iigzWY8 zB1itmhZrAj!rX8~<3kD%Vt)WfUhYCIgB1U}3=dyDn%%)uPvIsVQ7@qxi#dT+Q&o=@ zAvRb&tp`~V(sEqib`Q1~#Jcg|9*>4Oy~cr@F%Asrl6O+{V(7R8rIqWk_4o*;g2CN8 zQ$gSQd(r(ML&4y#j|PkfsBP1rWbFi5Jq_!Hu@Kd;r-L`z8EyuSJlF>C%L7aRy&(-p zG66sXo1h86*r0oL|L(U(VS~M!Y<2#=oq1zb{)7w-)A}dQA^K2sA5ZnnaaUep^pmGJnyeQcQ(H4kgpQRO64;1i1N4!5$PjD$`!na}b%lBY9+f zi2f(42y@CIpO3XA8L#i-f+R$SrUS+T4jFzFWnsfs-{+GgOOQ{Zw&`KW*ER*N@AJpR z5_kco#}y!=r>Fj^*4}VwEHTyoQ{}^6xZXs)Ll2cmlOmr*Ya^6b>Xa(Z^Fj)@dwrt? z+~U1*t(vlXc9}SP>6@NHR%hkrMpIlS!%yYoNJaDpq^ggaQ_8BLtJot{eTJ<0Xs=u`1#~uXK>}n}#GTRs>&gfC#xH@q-i-G$=Hp%@;ohj*fqHuK z(N>N6b^r^j7@-L^d-725;I-7(sKaCfYD`2t*MUIY_%@$vP=edWrI}so%7XU1U$Upv zkwsx>T5O$cjf>Y^B3)AUswQdFh-e;NWFi!)xte+CWC_Z`8Y->Jz=0!tr1MyQprL>c&EZQ z;~L4fKdGf|u8lPp93zTZf;rsvNYl1Tr8z&SetgILMMT4rrGOtI;9<-gfi>Rx~0J-7TE3hXt z|83?P-uV71RA@KWetB&Z8SEsawpy@YOHjwog{sPVh3?}PJQ?o=7 zqSDi&NE%}&3S3c9*3 zEn>kHY@L)9L#VWzk#Q+Tj^*Es zOa4l$VA-ZP;!Li&ggBM=PNy~;LGyBnE`vdFP!I=-y97|MXR9X2)1OC21Z5PogLY6L zcfklNVOu?5?~G2CVIAH$2|Qi~7s(-Pa5&c-yNy%(y&K}zx+yLkJ)8On@AQ5(kAuu8 zKMsD=e%tVbjwy z^uROo%2c&Xgnyj7;hjvcqISYX7GX5~$O$Gc1N7EMX~|GuEiJ={@X?^UNu)j| z)T~$bd8?8A5ic%e53!I=-99WB8{K5tBTtVqt|xlb(=XEAYSJDD<~%C3^djX-Y`1($ z#u?vTE}h^qG$@zk==@0ugH;Jhkc|ut=tve+Nm7t_p9jL~E#&#u19#=Ig-2zu7*vh;t4M>*7z)X%xSZ}iS zRGz5WEGCk!;0{)UA7QJ7qiYvo=f-ws%9t-MNCNVi#cp+wzl+tHy*D#6+ki=zmIo|+ z8utjH5?SpQq*q@4J1PVyt}rcz?Ma+JrimVO{`B;Z?fDZR##x>ai%8J`&^;6Zt2P_^ zyKXU*)}coMe+}N46KPSA7)z|JDWYag&l3ZB9@6;xc9#lk>L7oltLqTw-3HuLTi0WF# zm6=BDXOEEfVQKSAP~7h9mql7V!qN+<)PXL1rt$5Zm z#iVelhp``9V;+hv9GOOrjD35-frH94Lfp)Cyn^^*+d@{nv+9^}1NF^goEa97-st7N z$?$tJSYE{^$U^?KHn;|Zb zq~6i$RNC&6=CfzJo18uCNa1~u^Z`BEwfOIaW^2}rQ}pfdQc`c#|M+H3q;JU7j2^`GIA!n3=V1p*js9*$SN|R&PC5u_zcKRW zVnjStY6ftSuQuy9%hhHZuRYYf)ZchBVUQXuHH$w~{z43fhrBlzFWpF~@gGs+SB=%j zQ;&FWE*98r{3h%yOC1kPpZ*XDu14O($imjQ+J=kq(*)$sYv~_ z_vZ43dBzAtsj<&s&l|Yr9+y$8`8Rvd%|NNqpHSH8+^o@Ljn0eh@3T4PR|jdtS-l|s zXygFmS}tVh)xv1tUD`*Nh>%sKFD5q!C+ct+CPLsQDlu>F4Jy;pUQqz*_!|_h* zo>dh6O_&<3>B3YCt3f5C`${CPctOy7_zV9}{n#Y=7tSP^-1Etf2w9OKVX{QsIcqd|RWf5b-9QnHX|v(P(J_wTXB-_b?zRAO)< zhU=HFYIh$aO-4{ViBxn_#sIWnPbvemb{Kp_h<3u|bhQf1(Y#C%Sz^vA22;qdO=kc; zinEo`1+Tt_JY9+*!Y+(j|M&V5l-gh@KHqby>pGMsLW~H#U@jCMN_w z?4<3KfqDT{fHabOa0F7yV^m78QNFr^qX7$Q=`>EqWq`JY*o^S12A#BS30_s_#t;_{ z^>XfkeH<6{7UK|Y;5^(?fCxKCi?T!8;*WtubmB>9f@2|75J^%Yn4F!^wI~V1jP4Pq zM=u9h#hJQXSOX6bK7i3COTl+f`B$Yl7>W?WUsR`O>6E1(ILs3JCd4EOehB{m_TC4+ zvb(wyyH|6CWsrj$;B%ozkBZao!|L?&X4l*G;U|C0%(z@Vm^rjJq_^_Rt0BU zKn#N0$y?>XXfn9sEY?g(-^YWFAv~Cq#HqUpEzQ@Irxs6^HfM9P+GyJRAKKdz?3@{) zFt$onc(WBo5ocQGQuuix1p^A)nVejMbp-J(0mQc`h?@r?8q?3}M0=WJ78u28lsSx6 zR!i$Vq_>3jQO-33%oK+3#%k>xR|5|nNPlp!Fn!bMF`R{kTtloW7U}?Yt~PGN0a-Yu z0uo1u)7%S~<8ptNju?>aSesT4N*B;(=TMQDC`y~~Suk}ZKaANbF%O7oPua?_rG?dT z4u~E}xFhx{8HEV1#rkQ}ddgC&4b{q0MrI=tFDIk$xqc%RZbZSgJn!Vpct6;>SNx5t?PU>69<3iU0{CyhpZ_sdB9%*_3W4@zUr} zh)atuw41(=(-K0M*DD9Dl5kKZ;h$si_h(ONvB&(6tzbF=y&ndRS37Z_ofl&lZTk*- zE&QW6C1@2f8g%sSnDj>Bz>Q=5_EKtZ5uOY7W09UA-`Yc)dw% zYN2W(Vut%GwT*gp>uCya*==5#)8Ic;PnJN~13|_8i)`FUs+?a)XQ8^a+-_dwR|0w$ z(t|pfSDSe|%&&+yGcSpoHfN^&g!|>yeyZ$E+Vg|$HF4_5rfjd}IF$|s75cK~*WR4u z4}}D`Xgw72qiE}ce-9!SLVu6SlbQ~9S++fh5ev37dt z$Q=A@;~+SsOUTXAlkV2US2QvUgp<#qRo%t7;-bNm@uYc4!~oWuUA0GCMymIvxnc)% zx6)KBZ6I?KU7}%&=zb83bEH@*mle`WOtM033ej66l_E!f>?*p3h#cF><^~49T71DA zl}%P)z&py*iotuuv;;R?$d*f0WTP&nB~H?cLQFU-v3(7;XY?G{Z0!1Hs*mKt(M2G^ zegCQWe7+`q#*`?7PF@YC2spDiD&cjcYe7H2;W8cc7(&atG9seqU_*9Z{GqVyAII6B z`Sr%ZdU(FHh4VO@ow5*8$Kv2pweNDs)8%rmbHybW)GCbxkNgyFA2Ayhm6s@2^2;fw zTgdlxT2GY-bH_Xv7=Hqsk!M3FcFnCH7uY!h&Q5!|FX6+4-_HJ)87p)3xGgHS-1k)V9R zt%qkP=QhB`QO1K$SC%Ld7W!kMXoZiF%%~sQ?xKT>ZdTUTI;v*8CIDR&VN=wM#G;9# zG^(<|8rzkGR-{Lg?pBw!c&8^{5uUc`h0ELKRtoV#MPrIy%XS+LUjj;I@ebMg$vF4b z%n1h-2%*Qitz!*ss)oQtIAnV@HSYqjg^+Jgj7m=4KacV;3K zC?d$Fr=-z$^yTs{7chjk9VOnC#R|m=GHlCu2hZ2kLq5#pO9#(Gd6C`OAMZ!hiY){# zRT~h}@RskuvZO3N)kZtO8KNxR%Qmg&MECgPXT)W#oZ8u*tX2m+V7bfzkX@2S(}DF} z3?C9ZSFy01p)MI{m#q#)wvdhHS%OA_I_+m+7_z5qn>xNH;k8i4kmI|i6gFy)CVGKv4!+D)YH*I|pviZsQuel3A_X z1k>rnX#wm)_f-+w=ntGY&hs-_oq}>TX~ocfCOM^63Bx{3FPxqumGUf)3PoF_T8B97 zA-sr^2vOuiWUQW)Y&u+{sX-kfdHG_lvmPQvHpng4aXPpc^IP~-4c!w=r=!o%aW$7_ zLf*!ZtGHXtS>mNF3HFIunt;3IcgS$Mr`*NcBM^7w>GC1y|5WJbD!0Hih_v z8f`B-(jCvB1Gv$3OeNALm$YJ zaMeUkNpB8NQ7T_RUIYG%Sah5FG!3JPH=`wp=p#_~wQYx6a{)9(2O!(0QZizD(+pi; zK~~Sj^Id(A1QPRV3yB9-aNYvCEC%g0+;;?F56=4?4AB#&Ip;t9M+}O0ccnx;oOg%%Nuw^3Nwl5TS8@HamB8^JzmQ6b)6~vrCb;JQD>&V<&R}ed$ zZaUSqah#!>x_(1ERCE``17wl8^#yQn>{yzKg`l+b(mBhq4_)rlC0cR$Wq%%f$^)b4 zQF*E)n{G>l#31RE=?E9IBhw>7_kLZ``M{&4v+}o#G#YR9aa{&C;g!Re$4&T7D3R)S zYU3t+Lg|sK4~?p+6G)!$hw3QjzNFOB{5oG24*X;0QoNi+KDRb`x8Wpc^=^M$z1z1Z zy`$#cW^r_*p3h_MK|8NxI*JyoB`15j?47)DVwQMrZfCL|W=lIu zf*Od2=<3vrs3K8jDWP5i$jqHxSff6+==}ne@zf#d zyx@KIJlPP`1AEjw6HxV~f(w&r-yS^3&F_2+CD9l3N)!E1)dYfv5viHLyo9Ark7Dtt z=uoFcOQ(ud2J3@QV4JlF=L+tvT&W5gLIsq!eS0sn3m?IT~0wa|b z_)(02JUn69#io-Ab$kqo#%w*};`W$Jqa6;sQxETTvjKE0>Bb_Kbs>Y-86Q$X!2v!; z%-cm4KB3)!SpKRlKY9$uJ0O`?iNIwAs>Kz0C#2EgyTy7(GBHbLizCY1bvyO#xSfPR zJ8vgs0?!9h^9=;i(K2kaXPUNIeBuWewaw7O0gWrp0Vi&Ipcfr56;Q6k&|#;g(MRU| z*4nn2ipLoYv(1x6A94l1iWzuUv3J$Yz;Xb$PpExDM8AkTK~}+NP+5j-xlTJlZy`p| zIfLi4!C8nsx6XKk3vApFoAVKq$TrY|h81YlFw$_Zo)RP+#q%54TDeKoY4>nZ++Aou zI4^Ied8e$X2wpPJ4Q1}S998_7?x-hiM+sqEJ=w9~`HmYtkyv6&^Eqp0cg5?#JqSHv?XFKd9g#p3> zlNom4EV4KWJsD1j5MVDv3MNLP9}wu=cX+_ylYJ-Hs`)vH3?jV+wduIMa^Bc@eWyj; zH}d64U3y~FaemodP5uyX&{ERUEmLfL3t|y^Lb~L+`^74hmbfunfD}_F=Y#e>%?I_n zvA=~Vq$wxp65omWnQP2glX1TmRa>7%W^!HnfPrtQ#01{xj#GEe3rr0~f^6X3>mL5)k5X3ar9w`JjM4Z6BLH4Ip${_xOr*qBY}E;Z;SzUK>4P%9?!Ho~@s= zF?*la#}Ee#nYG>s!|RIqPr0pNe4kD`O~gf=kXF6q?@Rj@a2&yogwc!G(M1x(6-StR zMVnAmMQ14zNK96gT2z)1vhv7x$V4n%>b)E~bL6D!eJECw$7@6Fi6`t)lF!M~Dk_TF z($6z@!bsHv_8YkUr8VyrqUjknA9J#0_CWf|gX18erw^NaS|z!9~(}&(t#~VUKF7eED>9 zwB>l2DTe&U61++%$V{Vq+7fb#Fyf`MG-t|U!P5_65)DqYB{Ij+G?k`_z}#v%!U~^} zqb^!ml-xKWK-GP)aicTxaVT~6^4v3i)y?On#HOSNzhVx0mqu2vR?aQ6kkv(7E2~J- z0YzD257ca4xhE}IG9*|DX$AN_qbx0O!ANb=2|+wopXGgyl8w$$Hf<4S2S6^|TXMT; z&YI%m`#Wwa2O^iI&AzJFHsH*0@ZlTD32c9Ppmy0_xmR5D9=p@;v2B9F))BjG+xAmI z-C4>EIwD91=xyLP9e5>@q2N&K&YsV=4i!jS%LK@yVbbDPj)M~ z#Gm)wdKjDrbrx>V?&xJ7P-JwLnQ~-V=bzi!5-&gTsrK8L@pHE^^Ro2drD%l{Aui(_ zZK`8l9tr#?B(NfH3+k_Kmx(_S)ZU_#b!;c59acLF>itRt=>Q|G??lh>9b5!E zT7s__dKSf0;*^IobsgfAJvz`t+XccLPjRtmA4_CWbz6nF)h!V8O$zJd0&rW)jz;-j zJOj{N)uS%$Vmeu6c1v``1zE%i4+lhxwbBO-@xrAeuy^Roa6BP?x;Ly9O6Pc>6M8OP z0`5BUzl+D*!@zYX%x$c;;%*Kog08#`cOy!EsAGm@u~WF>s=?>>OlEnT)On#^dQ#h! zj)q7_yJO;~2A|%UUYb7trKT2s6AU2#@tp`^%CU(Ml-+Sl>4AeCm5f&oHIBkFdrlou zr&(E$4-;PE_VM$O4++T%zeyu*hTRyC*ykEZR38v?0&+9br+M%psw-luPxeW9tgMu(XsF+_aX7kqd~+6gUnFGr3dvG@p_b_DJEn3`!C%)i zBsFIY<_Kc7rLjBX;z>JX$FjVb(T=7~Eu*NHxMK_bsBSC_@d()zeX?+qVu2TEr3KFr z?R~@mY7aSsf~il=&Fk`I7(*`C(cN+ndz#+8jWwLvmT3+a-)*Ze87xc4Y*;PBo5dem z2&*6wWH>|-@3xMY%xIfs4aqr;F6*TF6*esnEmFRwqaiO}DQhp29;CO?QG=t^4VP%< zegJ7W+GYlvq;aihh$_GZq*=`ys}&>!I8t^C0;<|B<_|Ac(QwQY^G<^Pr-vVq^LJl7 z()`Fot_=yknY-Af>^e3td^?RkwMUwe&rPGEZF7ek`LK3s(3G0r`3>K{lSY0C8$KRH z@|&tP144^Dln0%DaTS0Vd;+@(}+`WgZRaq||WX@0MO42dPeKJ0VMTZE& zV<5GnzOz(yABif%{#NN51GjheIwMotTe z#V5FtIOljQv`{q4UzQu%+BWqk9?k*SI{J6yJ`O!nfGyUfxKvi?p+4`3m=d~?h32c;+x}`c!^sw8FO5o)= zqh$0*@tv`^?K|IH(O$KqCu;X?_v+E<*fmH*iXr*3WTlZo*yoVWKrim=K`u=@uI)a% zeP<6a5a;sg+F=dIZ(PX0wMlc7EUV?=9QM)cg1v-f=K-TRy$vRyYdK)Q>&n@N@i9d0 zS3|ONE4D{JS-0A!wz-2{-)VaD^&4u(Z79myqbE5omyIvG3Gmgg=`cM~Dj)Gj3K zB)6!})Njjdwvm$&j_Pc*M0aL3)(=qpDDcIJmv6sP8LNbp*W=Lp23lD;6~rO6Sp}ht z4e3{=dbVd!pW1~%VX7dZ_sE^3{#iexnKfxnW{x{Hfsfh{$I&Ua8!*&MNM3Y;lI-`h zvPhw0jL3GceY;*MRHDo4=uM=}9djh(q;1G!?lc!5@Go}rI`EjTMr(X02`!#p(e+D2W=Vxj6XyFerf_d7n)#b zu|(G|1f8IlY|EIN(Y>8AuN)9KboqZu;I|2*YkopWy+h$Lcq&^+2mpt13V|f}3IOSq zdrI?k`fP4nLQi7$ER)wGS42BU+!4WYvE#ePRAGtTmUIZFGLc^i`2FU9RFfc%3n=#3+GZ~<)1ALrS{nygu|{AQ zMX@}&ItGuoHn}BGIR=#q8Y039pbe~oo~?lp0VzO{6DaqLAgePrkASr1bDo18(VDL& zZZ6v2Kk~>d6KDxS8?S@IY#Lo3pI$}O00z-{SS3ymMpZ8l?U5vMoc8VhpiU`;vqa< zuU#{UWorh}6A!U2o-WwhYG2F)#dun$UQd^IZ3q#KUl~i3l8zuOYM6{x1=%4sz4m|L z@hL9lrnUXUb@7}lO3%$;HR<}GbtC{0a>3~a5}79!E~!NHMV9i-`733MtiHZ1%^#jD zPU922b3meUVml$CMs^RHcjCRd(UeH&@LeVrt@5^lM}aE0E5dF0D%}oUAkt%E+A@dG z$=Z-l2wkFiGN>`~EAlQr(FdP=s=ym1;YGUCZ=FO4Wej+i5-C-+X5FHEZhab5%@?MOS^D0`ur zTS+x}jZt@!P+=3*kT7NUX|;sjw!JUHXd&l-sb8P#jKGIq;Km5ikJ55rzlr8u+2DR? zxvSVE$CCK)q>A&qbtLLK@*x`m4-6|s+%@w)Z6WAb)i&nT6y~5M>@*kO1fWIIx!7G3)W{Lmha77LPtzAyeBy6Up!~dx)K@9jMl(ee%u6Xx)ZS|bM zUxatVl>2P6ps#|!Aw`JG7LJ~}i$Z+Lc*7lgsuOKhGu~x2%EcVqDVr_9&pm|mOuX}B zR~4kqPT#qlq*<_Y|`85f1g=;2eF(ZnJNMH|d}qYbScQG$exAfqxMl zV&(M`OgU-bE(U8Vjm+iM@HbUh#SbHFWA*$hSPE3ATVtn+XcK;TCI}Mw4eT}Bhd!h! z{xh}UGjI;yB6&lM=i3&G);PLLMfgdPs-@C&JLSzlAB(?z0(j$tka zKLG@}o+<+Mv$5jEcVF`Fz#*YD%-~T`77Hg4z=My?;gFc2S5eMqk!DAWEI`LMt_*M1 z(IKz_qYboMtuz{FrpFuyoXx;$9dU76ziYVo0h6XaQ9a4l*XgOzcQ#i!=N1!R;1R9n ztNJ9@@B__N35PYP4!W;qa%M57$0_Y1KWym0fub+_xoA0l#n2b`R)`@gmm)pI3HQ5* zZDrOwR{G?(NO}pv*!Iufgt6W1>lTjhT>Nv(_(g)WpKJDVO@OLm&19D>?Rt zKD*hYZ>~fA&!ncz&j(6Rc5zZ%Irzi9(I1>&;)}<2m(A$hY%c^cUK9h5%BE`_^)^T+ z>N-L^UIcPpKKRX@sj4$lE~!AOqaM9indazZJ4!lHOxr@CUAEsYf!9|IKd2sK5m#PL z=iLjJU*_+of2ovGp%&PpCjXZ;lq5fz5%H3!iY?JMz`s>T35O*x7n!xHy$j(l>P8OxiynQW6BH(Z%uM9JN$)|vs4b*pt_hd zFx;y-yvJ#-C1h@To61=MSOE7+&Y8`Loy{m;&9|iy!V4>FFhqDF!l~19$J9P5y3g=U zI1A@!&x@^V%||nK%5*a#!NY|MEnCN#lshJcwI%~z3YE?v+i?MjWy{&(d2~)xirv)- z_EY0mySzb?0F*>3G?ta-Jpk_WatdQ}n(p>aHs%b2FPHNwEz{^}UoO_K_wc zE>-uI+Bk{5j?_jX!0KT3@1khOyJ$@>MlDQ-fMc6_msgHIvRl22GLv1(U0B8&*sEiJ zWhSOA8@<^ONRm4ZLc$a`?#|nyoJ$fG1j=rb@if4_$r$MWGt)GyuZS_iz zGHb`jn)-I5_aWWboa*6t(!vut|6tsEKHK_299Qo^r_XX$ru%T?@NfaQygA#Fid`H- z-7nFaFU4_V`)zl@x0uUaZjp$Zzfc41I1RnEqJ`d z+HIlGfX9y8INV|agxH1?Z^dfPsgQt(QVHq?^5{4pAGeuWr+5!`Ek4d3#a~W%`sGi* zj9cWZ?I!t~AXpx!z#^*?p793PgsbrbRc-f=AJHmL|J<%h%w^dOS0Da_lsx~qQTbC7 zxq1d+Qu&JSKooT6(s|7gG1eyh(2)SbEu9HUmO}NBOD8FvWDi8;y-l7#WJwVG-&Xe0 z(r{uI%e-x*uGA=fE{-?1v%Xwg12D-p0{o{Z8{~)NJ$~zm1JAjT|7^3s=Zh!X_OaN; z0ntpNM6Or7=!O-So9XeaRWh`W#J&T!lTurLiamTzLp5+CVNF*omxYoByN}bPdud!D zhpx8QJ90!5WS!|A(gF!_8rPjnT_(sBzm(P$yM`CHZ;MxrzDv2_OF-NEbp@Ff|I)KO zx;!t1pp@6`y_?3{AhL5#bDxN`tI+Es#a<%+>K}hkd;V1jGJ&TXw8X(W>2cl!Z^=Rn z)ScJlCV7#UPid&BF@F^{nw#@S(&b(RMt1ccg>47^lW)lLOg_k}Y zzbzP#M}3TsDJDNNbahNFF$BX-b8=LjmjF!34r&mUQ}SR$|H&VzVeV7r-M8=&x3{5c zBO{bm9_n%Qua{B}%_6h?Po80ZJ#l7BLPqI?FQ`KP1M2!Ddm-=l3N!8@wKW&Tk}t}= z6HP-AfTFKVe2Qq3FIX6cA5uQx6sk~AT2DU&&Z%Bhox!`)3~+F@Z8IPr;%$XoHj(qA zm8xmai4=dhgfIDP@A2Cl7Dw{{i&u$tVxeR1!`Yj25OJ^U;e zoZpS#RixbIXUH^^m%Pkk}l z)ibnRr;GdL$&-oS>(f}v8P0ZOZn!Z01{gV$Fxwkh6(@yeWfa+MW$U|o{0D|vAlAwr zh{Hy8m;2AD8k6VcDBAu8HE6_!;L6=8^+drJ<~YOb{|dW0@OO+h$DMI{AR1c1 zHM{5%%s`Pj|KSW*M2LVXd>h#8cs1Cge;Iw0%%4(l(rwS`@nubI1GYVH&k{Ouu@Pb&Gd3s^Bvn(&DY=9TFdIKMJQ2ktZAfADVL8A6A9kXsJr1I?{ITN(R9-x)2Lr) zJ!JYTT~UN{rcXBAH?Zxt0lDkWq-Rq4H!-t+etiRBij{0c3E(KQ%d+(-?n5_F@Sv3> zI-A6erFFEToY#@DF}?H18GY~#Q4|f&)T-x8Huqd<*xgZczIE;=iA&}i2ClTRmw?JO5&^IdRAQ;8>{0;khRMEa;1#e$~^Krs~gA; zhS;@UO72_6#+q*#8{<^bz6c-FJ8B;TR?j@ua;3gjYAh}fo+(|>4@(9i-+36_1|Ws5UAmYO0)I zVzR3>rhO*SwqLQP_a(hk+wrt*`u;OnwX}ul#%FPqH?$+37!HwHSxurR;sIW<0ww}J zd-em7DDcSy!yL0$cKq!E&GmOA@k2Rprzf{zoIn-;z{Yw<(tBb-14lXKvOes_ z?#~v7!bCVlK8})EU?X}o9*{(J%(0R5wqj-b;vODH;S&|jxn&4ehVwAXyZnW(bGwC# zwjFYm9+}X?&J<-Cs4IDr#6j`sdoNkm1hWgoafh`)vy$5SRyv7e)Eu%;!IzE+x{?pc z1kCqlO15;cB83gDfLsswJcfEY3F14RUErSNY&Z)z+Lt^rC+#hnVBP?2E+J&ev0qAQYbx($+3ktpkz_&Y3NHcCK-_{y4`Tu&{W7H3uF5PK-Ov7Az>qH^<_`OLoSwNbtpB0d%!>4L~vqe`X*Ttuh-s5&( zfuAf%5yOQoXCc`R&wW6S{up#!zW|Nku#`B3sb3DTC&2xe#9jr&+uuRJ_)#9jRu1oYMe_VayNMNe9K7CU=KQ2bzz#GSAJlrHb|LCbo*`|mm{E8^ zj=XR3k9#U3rnm{90j8t2QD>#4VsusVIA@`oi=T+3HtV&R!<&x0=)8POc=@}Nf#}^A z&H8>ZQQr4UNnn1znDmU8NC0Lww~oy4|0i*ZCo3ImtG$6i$I+ntI0xM={&?IhFQB{m zbed+aJ|y$bQ{(%19ET|o)JOhJX{)bkrYQO)d|}rwCeeH4OW%htecwfY>HFD2PM>YBKNGy*<@xZbWUF&Ck zfS>jLB>G^|+l27#qNcFlST7{Z^)U#smEjVhWY_E2Ihw(!+M&=PEek&`<-QB;J;4g0 z?BsY_oHS$|?RhJB^gK=Olp7#zzN}o<*>mi51@iEwuVZGiM-;4bI(!zD7r2Y83o_?= za1mn3;_cW%&`WD8&?%vYWm;ZICZaQwOb{Smsz{q%?os2eVEKcS8*5eitgg%isF7lze%t2ls>+N}Sk`&-pq`Y`JmyZvXdWFvS(;2A6(-mhMIUQF zpDvGWh1~MApd%jWKeh=gB7O|!SiFBhd;jLq(k6ExMz^a{y|()CB!1ViO>!DA%QG@` zq+XH;0Wu_#MRNPlM3M-EdjDeD&*^MP0C5>$Zv<%w|r?M(6 z-W=dvk%Pr`o1zu_NusS6Xp27G9*lxhtb4-yx8W@6acu!}FU(mqEe}M|Z?%8fs8EIr zLG`pe77vV?g`(LU@#m7Le}}ika!kSJlDPRX2p(-m-{u!c=KLuo?Gi*>Q3sOK(dxofQiShq6z!UND{0#UHG#VLIr~ zoQ9S4Fx5A&Y9k0D(!>|ZN|kDhl;}#n$A@UlFmmD^W}_JBp}8DlyuYk!uh(|d{b#jY z7vgS{vshZPc!sAZRS%YW-qh{%Bx&$QwE+CvARINlBJH1EJzLKpyJSA$$OWCr8IIch z4!A74CN3{as?)1TZ>vaCa5fTA6;_~055s^p#J>dx_CokPWG1ceh8V0YHocNVq@lK# z?g#IuF!#H&r}y3%<7S#j88MY8u?6UB;ueO;vp^T4FKDT81iP&ZbL(vm!z(VCQL#G&e3&I4y*zmuHkn?6VBL4nBGM{n{T`yi zQE^(hn<1*nN*28$IYgxorSWotT?`BGqrfty(?RoJwG6`gbqrE63g3)g*>kTTL^lCVFw}zM`}JBr9AkF=h80sl zn?ou4**X{ojO%O#sG%$0gMj0<(dhBI7^__bs@5B*AAy^#hTiC!7P<~*!=|Z3vc5f{q)7QP1Ou;b%N0R+k!(*nUpolDj*E#jw>ujiiho)b&lTF8J2{V-)y9x3Tzs>utb z#q-Cpx;f3+GErg{Z0p@ z4Kw<)H+1#2MVE28to)VOC-<8;XJ$q_O=AbuCi+?jIH$tmI$pe8jT%<{Nh$#%_#<{O z4qQrFYtcb&hW5Zm-{=702r>B*!}cxJdLRBm9DQ3>{!8&d^j-OD;45+T``bWotDa3Y zThGytq8Ck?UKExO%9$uW%6b^zGquM0aI{LRuH-Z1W$s3bXD6#fOq0lYS$WR2$zlLXXUy*SYMR%q;BIho-&(ZgH7l>H$(K1$DX7%_ubq;; z>i04gz;YjCQZ6|lsDGpK6_Zxe2wm-YV!_p`6)yT)D9^P%67FcKl#l=-Ov0Q_eM$4G z%$1j*%J6x~|A7Q~IpWBKoJVE>_tLXQRch!lEOxQMe1oE9gy>Y%HPZpa1kYpAS0pDq zP2eLKwt@g1hc8&uQ(&V~b%Ul;onWv9L`KC9Dua;BiZu93Px$*MbeWLQ0BuK12WW^; z5SW}K3ZYv^c^rymI_aN$AvKi29N_KI8NSpT#hEN2LsiX?R_otPzPGTx3e{b~>x*5r478 z`X45JLkPNBtbM;^wpSKUz(33CUZncazknlwDvMKR-56aOGSs(!Li@kQU+L@nB7aL9^&eX-*GowhcgN!y|IGgk=g#+&UKeQIZ|?|D!!nNkIEf2y z-8g((;dP_;MYxKhedB<>C;F4zllJPJo{YQwi~0qS=9{~_-D?ivHQn8K&4j!L_==Lk zRoz#2U(gZZBUpCUu%6%mTMm7<2=pBdCfnWI?6>v z8UPJX^(Zr9j(@K1Jk^v=#Z096`(Zs|`f-_O79)4*fX#AE=UK*emd2)=-_K$eHg)6sD;QH(6^s-moh;TUEdw|9$PO(_@mt} z=tVy+`8|%4!t{zx2ITG6d2UWX5%7`O*ewacX?PYd)y^<2i|*SR4_0`YlZLU{I$YY@Yf38_5NDndyT(V`2LE&R`>?}wZeCUzgGBu z-d`(xzu>M%6}};Vt?(W2*9zZ_{#xPttNvQy8}`=<-$8$^@TLA*;k(ISD|{pVTH(9d zT^~~TZt>R&-)sG~!Z+%#6~06MTH$-0zgGBO@2?fU!~R;~yVYMSd}IDv;k(UUzfR#h z;;$9H+x@k|_XdBh@V(JrD}3YrTH%}U*9zYq{#xNX>aP{PNq?>I9dp;OSNM+mYlZJk z{#xOi^4ALAw7*vP{yl%K@V(hzD|{#XwZeDOUn_j4{I$Y&+Fc)3_-6dI!gr^?R`|~N zYlUytUn_ib{#xNX>#r5QyZp7ncelS*`0nx73g5l%`c{SSE&f{Jd#k@z_}=EP6~6oY zwZixB`)h@7-d`(xMSrdEmHf5Bx8Sc8zQt(J@n;3F90nA^EDR`!OJP7^JQoHO$mKAg zP*%c#g8B9^pm3fK0}5z03@D^4e&A+>bTtepq_r@hkgkORh4dX^Kp|ZZ0}5$93@D_H zFrbibgaL*0{xG1BUho4ZR5rtaLb??O6w-Hw0fqFhg#m^1U12~WeRmj8NdI~mP)PrS zFrbh=5C#;|U-SbeUj9ZHP)Ps7Frbh=7zPy5UkU>X>E8?k3h93o1{BiwgaL*0yozy!@hVL%~$Ul>qG|C2DFkp8VOppZTs1{BiwhXIB3SHgfo`nSV?Li$J; zP)I-E2TbJrr(r-L{nap_kUkm)6w(id0fqF}!hk~h>tR44{ZJTCNFNIW3h93q1{Bi& z+z*)Wc{~g#q#q6g3h8fz0fqFx2m=b~N5X(Y`q40;kp7opKq37*VL%~$A`B>`AM*ny zhW>6CP)L6>3@D^eh5?22<6%G{{jb7+Li%5a0fqDvVL&1MWEfCL|C=zNkp4YCU;^n= zVL&1MbQn-b|9%)yNdMa~ppbqh3@D_(6$TX2|1JzDq`w^o6w=Rz0fqE)e!xW2e;)=E z(*Ge0D5Ot?0fqGQVL&1MAH#q``agvMh4kq#ppbqc3@D`ka~M!a{}(rK%ZPIRFNOhy z^h;qtA^itoKq38yVL&1Mau`rZzY+!%(*HFKD5U>e7*I%`2?Gl0@Av_eQNJ4o6w?1a z3@D^u4Fd}4*TR58`hSE0h4lXn0}AQa!+=8ijWD2){$F80A^k^wz+}`n!+=8ituUaF z{^Ky9kp7b}ppZTr1{Bh7hXIB3{|*BR>F`|F0h~8TDKkP)PqM3@D`kG7KoB z|0)b9q|b)|h4lMjKq39tVL&1MH(@{_{XrN|NdMRmn2h?jVL&1M|H6Pm`ol1wkp4*+ zP)PqY3@D`kE{bmG?EA2zDc}oQ%!b5m0uRt)Wqw&HGle-uG7%0j zA1gEIIV)#s;8lxqm^jkq>3&Z&S5_A$jtVHF;y=lI1S)r{Wn;S;^vQ9!=sf`S6WOZ1 ze*)wo093Qpb2z`8M=>mHHM05vjrQO>bD*tBQ0H6*z}AO5fH)|HDN{`CjT6w@0|Md> z|Cc<9Y7-ndzNFt+&~y>Wt`N`}8d%Qi>8J;P5((onIrd9(dtC58SR#)5a)%I|2Ib9b zh!vq{y~8yUU{Rfo(?t-dVh$=3(GR2pR-41fF8)cb1d3W0!hp2w0yy_sn#oiM1UH!P zTFf@H#f?TbFRw19LnwQ~P7$m`dqBxrfw#K+Uw1645y8M@s&!zC={^WWt+Ix?vYI|qm~N2Xd1@nXzEG(nUbea<~p*b27sc zt0Zt!VQ4)ANxlzaA2T)UV(8u zeTPnB@w{?|yfVb|04-k6l8h1%4vr*!4cOq*(%-qX#E#6NCwUzMyVvsHY6aD=2N$c% zHI?mM1xzv%9|1+If~=9MRU!KI70BCKJWmv?Wcxk@t__2sYhanEdJI3qdm4tvw_aJR zB5ykX(w_VF@KRG5cu<`z2N)Cag1(~#f`g?&LlQTy17&JEERgTy`G}v*V2Oe1-{EJg zXjXB6p9*XIjZ<>fl%d7HAIEb8BSL#B+UtKDZ^Tzb|FZkWIJzQw&zZM3x}x#8EBnfI zQGCTyzdL;Yon6th_%r&apF4ebSM(gBQjz<$@%e{WyHFW`U)_WF^EV#(+3UKZ8NG{A z?U{nSukiCh9HJYEl+@J6kf{nFWs^{1GMNskeF&7xGf*C&DqPt$5=BQa)r|Zvc|w>T zqVduu#MB9Vr?KsvW|1D2X{Nxkgh0SG!8b{i2=~j=fpso$LpoN*%}&8RGH_8So;PO9+oQW^~Qm;Fu9;ey}E0BeDmF^5`O#p-GJK5cGH*ut)p$K z0)hmewWoW<{m%9xmDT%e=d*Obg*dP2`bO8FJQ)b{_lSW;p%AoPshF*|KJ0^_A>nayPtjZSO3K` zf9slk`1{}d@-O`Ici(vI1n>FHBi-ufiN$?KjV?-OFeH@vnU5@jK4{`oHG0|Lkx7-XGO&uPpHItMI=lc@U=&Sz0mW zGV~&+Mu0&xBAgD*&K^2EvyOVT%}>S%NA~M-1K(2k3Uu=Zpq_Uqc|#{qDIeWRri)96 zt!fFHlFh(j1k4rzj*DyT-so#w)NRmZJb4+K#Qf81g87cSz%OsFJaWnZX*af$c zTM$z@n8$%)PRTyPuLch$^G9i~;5c>iZvu&Q)lz*86kcd^#HDB`@eQba@D=Q4ZL|)| z&CO`_*Ii5s7hZj|R?gxG`su*C*F!aV(irq-?O-6h5WndHpt^1a$7Vw~V=*zrgeum6^R7*Plpdgk zay0oaS(JmeB{JI*PNYj?FD3gTk~-|XW$3XYf0<|{M`kPg6XB;CGhjoX43@%Cvxe%+ zbbP`r%sV|CzK%u{JOEuu)ccIE>bDkAyoc-xK;L{<@jm%@wW9E~^3wF6K`av!K`w*O zut9u@M&uhUDXH%<*X z!-RG8`vJ$49Hwd<-3)~9-@pz93qtKW_NXSlLp2x5feEU*K#n|^{Vnr=3dvrz$ru!S z&t8;NZKtFqVKG{8e*uiHE>)7kRj^KW_$Jrkt;KEo0E->&0hU#N$KES%EN0~@%k0a< zy739{9f&=`kw)(@ig29ES%M|#p>ix7_#M|x^6lAKgaxunnA>~@0i$AQ;jxui7shss zN{~Q&Yq$f(gDZDk$x6`Lz|Vcj1pemB4LIX8?)jn+PiYBef!tMDrK!5wNRON$F|afs zn^~{bmZIoZEa1S?LMS5K$=L8=&c~n{u}~1c0aG|D74VDDQ+^H{6GWF2t6d(;1=-k2 zbDqL-t1M*hVIvHXuh>7sCu2we{^i&#F>B~{_YW7c^jyk~*2+r_rBtTu)BHoI6@uU8|+Uapuot@W+YsY~mSnds>T$B!^L@qpt2<6z_b&Z+g4 zHTzI__wEC&^x?oX@Q;qr)A(x!Uz#NfgTgniu4c&aWdeU*lsniD zVJ}iy0%N``FQ4JdPj58D{TfhF!J_wmL?JMer42x4K!r-U`sD)Q@YywPjqvjC!}Zbo zWI=}=&Ani+cji|+C=wWpZNY%(fZU_)<9wIgj&u>Tp%2g_Iz4xo${N||>4UBrMOn6( zvVuAkX*8HnJ;|+pkIBH`%MfDlOM&g?7zIh8RYnsS@$QMMQP$07g4ll!CWbUs;btU= z!GY0k9*&{W474`b6X`OvRN+tP1GlEGk<+mL)?ori(IAqG=`;&-0#2x-d;l#%QrD5|iwues=lepw>30A-A{h&hVh6p*NMQv1fmsj#B zrY6N|8^vydtVe?v?PVw8M$|MRj8IRm2QyQk$Wd~v`^6d+O{MhVC>%;xn1z26CZL#) zFrV2qSSFtj`sX~~Gtc+HO5pM$x7FKNK+hj z4i^y}1}N%>(WfGvq6ia9jSiM+3-#RV=UpQozyn3u1!k}}$+GIw>PNRDF_o$ba2!iF z0nHI+p&jGBkUb8;xFMYd=zKEZVV#K`FeWNqZ|3M#l+zLP3`eCU6r|Bm;jbX@El)(Fg<`R|T4TE>6qJ9WP^e%cn|9uwr|(V- z1KD(EkYm6N_}8xOD&QZ9yI3G(mL8hI?GhnEm=8h7+2zX05w=qr8?$?S&sAgr~p+`1p0Q*i*InyJ!ov;uPaca>s>{eS^f=|XRsx6^w2Lk%elbfRk`RqC@ z+hQKWMJIGGbPIa@(uvsT1ONf}SA2n@yx8YSd_6E!b6nz1)o@zpPWw+F^dkZB z=)(}FJ)eOOZ3~eoG>j;t#EaqQ^Aa}|&w|5&11-J50W_&83YtgoXq)jm-^< zNkcD&xOjQ!p!_W_VdOy+AO+@=lU+Rh<=%13dBXHGJN>%GA0^a%$e(knAmnvYD$XuQ9GX>0= zaEQVyk+i^P*vexyEu1_%J6E{lSm8})j!n!RJ5!jOnmAQ>%ds=3ug6g>JUny@JN8Dn zpdqGi)NZNtze${e1&U}iXYl#slA-0GNp%R;2 z8eo$7YC9OL=aLiCxfVOv#C(EYGjWcI4&wW5J_IcSlT`>3lsn!@)mFX&sE|HC(R0X4 zX|NwLS|j7og2|eEg7%~@(W(YKym&j6|HioU*Eu&zDoo^UbO zU}@;q$m@pEa7Jj(lU@2v_Fn~$pvM~8MMk|2KHp(9X@_d%3jWQsfNobYrEeHexE-N@ zpdGBz)wcMp7Nq-KA|R2ow}XdYCws%vXrQDDv2L4mnL7%21#UXbMYOS9uP8x7nAbLz z%?#RVKQq1ZP|eu?iaY>`M>$mP7gtNg}2Y&`fbjm5^%x4=hGiTa+Tcp8eE#2ZW1riprz?m3Y8 z1ojwq`vyv4WquL;`G;`4giD4KeUcgk($)&ExxcdBkS<`Awb#f#uF z^pnO`QS)iAOTCB7Z6rxd!u=3mv^?hlhzJn%LSkFCyn>5~dFU8kf1Z6B!J)Bfkn&Vn zqdZ0UfPQGm613yoK#VvC1*o99h%q9(opUQ)Kbu7=? z`{oJK?aaUclnm!{H41-Kz%Sfb$UWFZM7KS?D*%`z_l^U%sRjpC2%N>Nr#jwB2L(Aw zGciyQ!9qpa4$mgmaJEGqu=2#0UuxV`gee3QhX#xVlyi%j7G@!1=)4gzFCFMOLGBhY z7?GRn(7CX&vL<;hWpD!sW1-b14B`A9azcQvkr3$Al_hn$LchlTrjP(+fLTNFB-kdZ zIh+RorqnAAPq1N{Pm;zaeh4jehSY<=<{WYE?_@y7vDcwDlwrcr&%l>9o6BSr{nD3- z(P!w`$p6D4$J>YcN6}toql!a8+2{lQ(r;5Ec}SQc!g~G}X!Vs%YylV1uBSssoqr2Y zeV0#tR-VE!n-T9K~B%LDLs@g@X`h16($3BQ?8M zu+vx?|4~=`NECm+>ze(u_*&A3`(yvmUFvhHtz&T?#oE40*49xOl^9^u{6e@X9XYB_ z9LaTb4$oxM`*t8kkyXvz0We@lND9&DoeY?ik4l~=&_vHp&#hP*%L?SZ(#E{HMMj#z zkU_Lz(Nc37?8FS}*CpT$P`2@tJJcm+$ijRc`09TEsw)x)hzo=^?5;2oc#M4o@^>jujmFPsYtZ!24g*MW z$(G=2*d*BLKq71*0L0n_Z5ZVt!yK5!3}hZi!)4 zgp{#wn%Cs0B8Za>mFmn<<|*<=vDj3G0n{a>i}N{bd`u)dZJ}@h#f9M5f9EG&vP1P2Sg%9(0>=nPi46~ zzGh$ip(ws~-_P{XgBHvG_Y5l^6QJYhI>K3P+A_+)Xr+?WhHbmdR%^)GzhPg29Gn02 zKG5`39lz_Y0c_&MOQT0{2d-RLia3J~MC|5rgi=oS>ivZ9*k&VkebI87hu2PQoGHnn6fRv1xyx<9Q3?Qk)gh~ylubQOS6o=Z z@D|b+RI=v#KSHZ-dLbTz!RJISsEx@Uc%c!eYFnrf(BOiiNa_7KGIi%1#xz`2YL<{N z`U%aSMQn!n2yrG zJ$}+cM{(TK)jhFq6q8&_yVQy(&OvuP2Z#$TVHE5&Zd&KeV5tI3031rjQ*~}qnwfIJ zz&x180OkNxC{jO4#SZc$jV+zs!N--u=V!nnYz2dzUm@XnZtUt752H zDAEOgz#vo*G%ldb#<&-q>(Xaf_$7#lWbHDd@PPszEEr+NGB;j~XWa2{+K#q(`g{=@ zm%UJz02$hMgK*(thD?>maZ<-RvO=M+n?jCxMcBXY(4p5J!mH7@EG@`ld-z}q;{h5C z?lY(;fWgzU1lDg8bDliJY+DK&Xx-xEG9r*eV?ce-TFLU3k(__ftDlo`n^giiu2(1e5`ru+FYq$fzNYdE7=m=h|7tG>ql$$KeWhtvpMM{XQUpqGuP z71OsYH;ZFTL>nzd+K+1x$FN|arU*L#UKgs!VZWtt%c0j%+m$jwoXN{Gj)o~QscmD4 zisDz2ch!pr;76@MOS-F6Wetw*9`7)`4h)fjRV82EDQdLzVI%}=m~Lppx;#t0+|BfG zf@ur5Sa7)8s?`JF6Q!jLJm)TjLTXHVU|-{)8`kYO=*X&6%i@ZvR5#Qb{G#5{=eVk+ zPk`8UE~Pkui)0n&>q0dJg{bY0c&fV_9Ec%RncK}5CXjsyF2e8$)zytv_^lxW+4^#v zoh?O8c3%+pba%aXUmq6pIa!|*sz%tf#2CIEs*V&M++Tus0RdcCx9W_N?v|J@9k==5 z7ePH2u!Dp6IPowh21A-a8cKM`%_*K~YDoAr0O~#k#O!Orq>=qfI+LG%YmW7h4fl%o zff9S(p<5g+xaqTQc@-HG&%aw-uPop_SR8tx-Rr0xKuAFR1Ft9t;D5QhSLhMc16Lm5 za^;@kjo1_rqHITsn^$l{I%hz_xLG8J*}{I=Kn(c(0I)YBk!)K*BMK6U0|zr}k9Icr zCalCfs(jp;HQKrx)QETieA!S-@a=@R$VxJZ5AsGh=v%gc-vA_K71@}Z&*ca!>}crsC3(Cf69tj_0Ai0K#>d zQPUUGBim+%82%)uefFZJ6)gtzg3{hOZ~KRd`dihDe=pa55}@G1OgCow(r2 z&SBccpW7Ed8G%*)T<+XXXb$hgshHhKp@8%tr6m7X|EOvjmMt6OK!KqvqVK$7u1mCw z6Wf)GbZ`a;pQhg;Mt9nAXeCYmB;)eT8pXPD`+hzkk-EOC6JTmmZopmzf8}l9^Fct0 zNVtZ#mF2cJ0`@Wr`}o=!@CD1phK`%8IGC0XGo(}bm7Dzj0cm_Ni9a0ox)W&bKm{TKnE&Xvadt`gX8@`@CzH}VbEbi0bO$Zs*eO-w zuyai<7u`q>{Zn(%zd2N7LcM6z9u#GXPB^ES$*0QWWJ2pH2oSHvF2}#iEYYHg080g- z3OT`z)NJ~e6hf#7f~^XAkP>#OTPu#j$-v9n($J82K~IU+HC(Vj{BU8y9r}8JWykEr zAoh>W2M>mu?SVq^wYP-X!ejPSI%;v?<8W2i)`85gqGB`mPw!bpW@kLov}6hnhynOy z*iB{ijtEVo8`@zCXo3y|i1m{!l?*FIZkZkQdXGb*U=F9LpxZRf9ee?Fr#?w9O8!8I z0IIsAa0U3q5YaoSk5B?&w+bn{g-6O-a-bh+Dw|ue{-RMXKg*sbB9(=*XD$NRIryFpF!D)Kq_cyu-dz zhz}do+`H)Ho2KH7IaOk8gx)e>RAh29!4O zm^nL|J5VQUVhucz985~1BRucudAy!)unsrMXXI1le92UG_n`wR%Djg>mH{aT`sJD$SKnh)KjvUq$gzstN)*^sk5iY_2|Elrbn-FY`5i%kAzFM&umsQroz|8k zM-}_IVVP}k!W|$DrM#=F>yyc+F(HocvIFoyj!<`HKTAj&M|MGO9A}3D{{v`11cc%r zMmJI^@f^|Vou-imm-}m+*LUN~cg~(~5;;yCLN4pFsNs0fvXczOwG?30nki)QB9vFbw zBjUh2iPQ_S0LL7GYs?DF(NQ6eP)mIh*1>!%IKfzm%^46jvzyfC?#}Pj^N7Zy@7+K3 z>KqD^9|&ndZ6zi79i|6z>HG#w)5>{jJs~u0TgliH6uLh>*~FTho^lZ{kXQgIjm{9= z8lKXHLylmVLm1$HC}=z37P^T;K5*A#O<*KgGgArn{I$yUlxwWGBi{gkfKoNhAGl=scF)S(P5|bctuWz^9#cJ}Qmq=A{8mOC ze?GYdrzj$c7W%IHW2pZqA~&$vuzSBiMp$lQnb;xdF(5f5=?RIkGE)V_h@diA8lRJ9 zb_ev6!|l$2ffEARM2PNtlC*1_2OkAW9E3H&)q)MCC)aTH9DgQ1{ZjH+3@?^hf64+x z4@QOv^ZYbwZ4=+7wk86M6>|62gaNV8}ve1tN z(TYt4T@6Z)@NXpV1q_3Kid0OG$OpR3b$Ut2;A@<2xtU|<>0oNw^wa!v0?0S`EJ{I$)f@HX=-%7sCo7W0{+=OmGNh(LD%^*cJBV_W1@9IM`m=`73r>Zlj zCysiGg)XY670G9*ANS4Z76f6--eP>ddGjmwH1S4>-r8!>8=J-xN&H)IRfZP?4$#W; z1q%b9oWD%?hClX!N{a8FM!?WRlA)HUta$pe88j`#044`Yf iM_LZ`xvqO;$W6bP-GFKHZEFwUx@}|HgZSa*?*AXZNeylQ literal 0 HcmV?d00001 diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs new file mode 100644 index 0000000000..10db80fdcf --- /dev/null +++ b/examples/parachain-example/src/main.rs @@ -0,0 +1,257 @@ +//! # Connecting to a parachain with Subxt +//! +//! In this example we connect to a parachain and subscribe to its blocks. +//! There are many parachains on Polkadot and Kusama. Connecting to a parachain (or any other substrate based blockchain) with subxt requires 2 steps: +//! +//! 1. Fetching the chains metadata to generate a static interface via the subxt codegen. +//! 2. Creating a config struct that implements `subxt::Config` to give some type information +//! that is currently not covered by the metadata. +//! +//! We now show these steps in detail. As an example we use the +//! ["Statemint"](https://parachains.info/details/statemint) parachain, also known as "Asset Hub" that is currently (2023-06-26) +//! deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). +//! +//! +//! ## 1. Fetch the Metadata +//! +//! To fetch the metadata for the Statemint parachain, we need to have the URL of an RPC node. +//! We can find the "Asset Hub" entry, by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/). +//! We connect to the node ("via Parity"), which leads us to [this page](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot-asset-hub-rpc.polkadot.io#/explorer). +//! In the URL of the page we can already see the URL of the RPC endpoint of the node as a query parameter. It is also printed +//! to the Javascript console of the browser: `WS endpoint= wss://polkadot-asset-hub-rpc.polkadot.io`. +//! +//! Let's create a separate crate for the statically generated interface. +//! Keeping the metadata and the resulting generated code in a separate crate +//! avoids unnecessary recompiles, whenever you change something in the rest of your project. +//! +//! ```txt +//! cargo new metadata --lib +//! ``` +//! +//! In the new crate we can now get the metadata via the [subxt cli](https://crates.io/crates/subxt-cli) tool. +//! It is important to specify the port as `:443` like so: +//! ```txt +//! subxt metadata --url wss://polkadot-asset-hub-rpc.polkadot.io:443 > statemint_metadata.scale +//! ``` +//! The metadata is saved as `statemint_metadata.scale`. We need to add subxt as a dependency with `cargo add subxt` +//! and then we can replace the code in lib.rs with the following: +//! ``` +//! #[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] +//! pub mod statemint {} +//! ``` +//! We use the `metadata` crate as a dependency in our main project and have access to +//! all the pallets and calls of Ajuna via the exported module `metadata::statemint`. +//! +//! # 2. Create the Config +//! +//! To construct a config, we need to investigate which types Statemint uses as `AccountId`, `Hasher`, etc. +//! We need to take a look at the source code of Statemint and find out how it implements some substrate functionalities. +//! Statemint (Polkadot Asset Hub) is part of the [Cumulus Github repository](https://github.com/paritytech/cumulus). +//! The crate defining the parachains runtime can be found [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot). +//! +//! ### AccountId, Index, Hash, Hasher and Header +//! We need to check, where the parachains runtime implements the frame_system::Config trait. +//! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. +//! For Statemint we find it [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179). +//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::Config] should also be the ones +//! we want to use for implementing [subxt::Config]. +//! In the Case of Statemint (Asset Hub) they are: +//! +//! - AccountId: [sp_core::crypto::AccountId32] +//! - Index: [u32] +//! - Hash: [sp_core::H256] +//! - Hasher (type `Hashing` in [frame_system::Config]): [sp_runtime::traits::BlakeTwo256] +//! - Header: [sp_runtime::generic::Header](sp_runtime::generic::Header) +//! +//! ### Address, Signature, ExtrinsicParams +//! A Substrate runtime is typically constructed by using the [frame_support::construct_runtime] macro. +//! In this macro, we need to specify the type of an `UncheckedExtrinsic`. Most of the time, the `UncheckedExtrinsic` will be of the type +//! [sp_runtime::generic::UncheckedExtrinsic](sp_runtime::generic::UncheckedExtrinsic). +//! The generic parameters `Address` and `Signature` specified when declaring the `UncheckedExtrinsic` type +//! are the types for `Address` and `Signature` we should use when implementing the [subxt::Config] trait. +//! In case of Statemint (Polkadot Asset Hub) we see the following types being used in `UncheckedExtrinsic`: +//! +//! - Address: [sp_runtime::MultiAddress](sp_runtime::MultiAddress) +//! - Signature: [sp_runtime::MultiSignature] +//! +//! #### ExtrinsicParams +//! The `ExtrinsicParams` type is the most complicated to set up, but it can be derived from +//! the `SignedExtra` parameter of the `UncheckedExtrinsic` of your parachain. The `SignedExtra` parameter is a tuple in most cases, +//! where each field of the tuple corresponds to 0-1 fields in the `ExtrinsicParams` struct we want to create. +//! It looks like [this](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L779) for the Statemint parachain: +//! +//! ```rs +//! pub type SignedExtra = ( +//! frame_system::CheckNonZeroSender, +//! frame_system::CheckSpecVersion, +//! frame_system::CheckTxVersion, +//! frame_system::CheckGenesis, +//! frame_system::CheckEra, +//! frame_system::CheckNonce, +//! frame_system::CheckWeight, +//! pallet_asset_tx_payment::ChargeAssetTxPayment, +//! ); +//! ``` +//! +//! The `ExtrinsicParams` struct is basically a collection of fields that can be grouped into two categories: +//! _extra parameters_ and _additional parameters_. _Extra parameters_ are taken into account when +//! signing a transaction and sent along with it, while _additional parameters_ are only used during +//! the signing step but _not_ sent along with the transaction. +//! +//! Each element of the `SignedExtra` tuple implements [parity_scale_codec::codec::Encode] and [sp_runtime::traits::SignedExtension] +//! which has an associated type `AdditionalSigned` that also implements [parity_scale_codec::codec::Encode]. Let's look at the underlying types for each tuple element. +//! All zero-sized types have been replaced by `()` for simplicity. +//! +//! | tuple element | struct type | `AdditionalSigned` type | +//! | ------------------------------------ | ----------------------------------------------- | ---------------------------------| +//! | [frame_system::CheckNonZeroSender] | () | () | +//! | [frame_system::CheckSpecVersion] | () | [u32] | +//! | [frame_system::CheckTxVersion] | () | [u32] | +//! | [frame_system::CheckGenesis] | () | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckMortality] | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckNonce] | [Config::Index] = [u32] | () | +//! | [frame_system::CheckWeight] | () | () | +//! | [frame_system::ChargeAssetTxPayment] | [pallet_asset_tx_payment::ChargeAssetTxPayment] | () | +//! +//! All types in the `struct type` column make up our _extra parameters_. +//! We can put them together into a struct, ignoring all zero-sized types. +//! The types of the last column make up our _additional parameters_. Here +//! we can also ignore the zero-sized types. We can name the fields however we like, +//! however their order in the struct should match the order in the `SignedExtra` tuple (see table). +//! Beware that some numbers might be compact encoded, when encoding the struct, some might not be. +//! Please check the exact struct type definition here. For example the definition for CheckNonce is +//! `CheckNonce(#[codec(compact)] pub T::Index)`. We can see that the `#[codec(compact)` +//! attribute tells us that the `u32` value needs to be compact encoded. +//! +//! Because the `pallet_asset_tx_payment::ChargeAssetTxPayment` struct requires us to pass the +//! struct of our `Runtime` as a generic argument, we decide to just recreate the struct here. This prohibits us +//! from pulling in tons of unneeded dependencies. This is a pattern that you might see often, +//! especially because substrate crates and their types are quite big, clunky and entangled sometimes. +//! +//! With all these types collected, we can create two structs: `StatemintExtraParams` and `StatemintAdditionalParams`. +//! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [subxt::config::ExtrinsicParams] trait, see below. +//! Now we have all the parts we need to create our config `StatemintConfig` and implment the [subxt::Config] trait on it. +//! Note that StatemintConfig is an empty enum, an _uninhabited type_ that is never means to be instantiated +//! but just gives type information to various interfaces of subxt. +//! +//! # 3. Simplifying the config +//! +//! Now you should be able to create a config for a parachain from scratch and understand the details of its construction. +//! However this is quite a tedious process, so subxt provides some sane defaults that can make your life easier. +//! First, let's ditch the dependencies to [sp_core] and [sp_runtime]. +//! We should not be forced to utilize these traits whenever we create a config for a chain. +//! That is why subxt provides some types that can function as drop in replacements for some types in [sp_core] and [sp_runtime]. +//! You can use: +//! - [subxt::config::extrinsic_params::Era] instead of [sp_runtime::generic::Era] +//! - [subxt::utils::AccountId32] instead of [sp_core::crypto::AccountId32] +//! - [subxt::utils::MultiAddress] instead of [sp_runtime::MultiAddress] +//! - [subxt::utils::H160], [subxt::utils::H256] and [subxt::utils::H512] instead of [sp_core::H256], [sp_core::H160] and [sp_core::H512] +//! - [subxt::hash] instead of [sp_runtime::MultiAddress] +//! - [subxt::config::substrate::Era] instead of [sp_runtime::generic::Era] +//! - [subxt::config::substrate::SubstrateHeader] instead of [sp_runtime::generic::Header] +//! - [subxt::config::substrate::AssetTip] instead of [pallet_transaction_payment::ChargeTransactionPayment] +//! - [subxt::config::substrate::BlakeTwo256] instead of [sp_runtime::generic::Era] +//! - [subxt::config::substrate] instead of [sp_runtime::generic::Era] +//! - [subxt::config::substrate::Era] instead of [sp_runtime::generic::Era] +//! todo +use sp_core::H256; +use subxt::config::ExtrinsicParams; +use subxt::{ + config::substrate::{BlakeTwo256, SubstrateHeader}, + Config, OnlineClient, PolkadotConfig, SubstrateConfig, +}; + +use codec::{Decode, Encode}; + +#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +pub struct ChargeAssetTxPayment { + #[codec(compact)] + tip: u128, + asset_id: Option, +} + +/// Default set of commonly used types by Polkadot nodes. +pub enum StatemintConfig {} + +impl Config for StatemintConfig { + type Index = u32; + type Hash = sp_core::H256; + type AccountId = sp_core::crypto::AccountId32; + type Address = sp_runtime::MultiAddress; + type Signature = sp_runtime::MultiSignature; + type Hasher = sp_runtime::traits::BlakeTwo256; + type Header = sp_runtime::generic::Header; + type ExtrinsicParams = StatemintExtrinsicParams; +} + +#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintExtrinsicParams { + extra_params: StatemintExtraParams, + additional_params: StatemintAdditionalParams, +} + +#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintExtraParams { + era: sp_runtime::generic::Era, + nonce: u32, + charge: ChargeAssetTxPayment, +} + +#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintAdditionalParams { + spec_version: u32, + tx_version: u32, + genesis_hash: sp_core::H256, + mortality_hash: sp_core::H256, +} + +impl ExtrinsicParams<::Index, ::Hash> + for StatemintExtrinsicParams +{ + /// mortality hash, era, charge + type OtherParams = ( + sp_core::H256, + sp_runtime::generic::Era, + ChargeAssetTxPayment, + ); + + fn new( + spec_version: u32, + tx_version: u32, + nonce: ::Index, + genesis_hash: ::Hash, + other_params: Self::OtherParams, + ) -> Self { + let (mortality_hash, era, charge) = other_params; + + let extra_params = StatemintExtraParams { era, nonce, charge }; + + let additional_params = StatemintAdditionalParams { + spec_version, + tx_version, + genesis_hash, + mortality_hash, + }; + Self { + extra_params, + additional_params, + } + } + + fn encode_extra_to(&self, v: &mut Vec) { + self.extra_params.encode_to(v); + } + + fn encode_additional_to(&self, v: &mut Vec) { + self.additional_params.encode_to(v); + } +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + // // Create a new API client, configured to talk to Polkadot nodes. + // let api = OnlineClient::::new().await?; + + println!("Hello"); + Ok(()) +} diff --git a/examples/parachain-example/table.md b/examples/parachain-example/table.md new file mode 100644 index 0000000000..18b4aefffe --- /dev/null +++ b/examples/parachain-example/table.md @@ -0,0 +1,10 @@ +| Tuple element | encoded type of struct | encoded type of `AdditionalSigned` type. | +| ------------------------------------ | ----------------------------------------------- | ---------------------------------------- | +| [frame_system::CheckNonZeroSender] | () | () | +| [frame_system::CheckSpecVersion] | () | [u32] | +| [frame_system::CheckTxVersion] | () | [u32] | +| [frame_system::CheckGenesis] | () | `Config::Hash` = | +| [frame_system::CheckMortality] | [sp_runtime::generic::era::Era] | `Config::Hash` = [sp_core::H256] | +| [frame_system::CheckNonce] | [Config::Index] = [u32] | () | +| [frame_system::CheckWeight] | () | () | +| [frame_system::ChargeAssetTxPayment] | [pallet_asset_tx_payment::ChargeAssetTxPayment] | () | diff --git a/subxt/examples/connect_to_a_parachain.rs b/subxt/examples/connect_to_a_parachain.rs index 655ffbbe4e..90bf150c14 100644 --- a/subxt/examples/connect_to_a_parachain.rs +++ b/subxt/examples/connect_to_a_parachain.rs @@ -1,5 +1,32 @@ -//! In this example we will connect to a parachain and subscribe to its blocks. -//! There are many parachains on Polkadot and Kusama. In order to connect to a +//! # Connecting to a parachain with Subxt +//! +//! In this example we connect to a parachain and subscribe to its blocks. +//! There are many parachains on Polkadot and Kusama. Connecting to a parachain (or any other substrate based blockchain) with subxt requires 2 steps: +//! +//! 1. Fetching the chains metadata to generate a static interface via the subxt codegen. +//! 2. Creating a config struct that implements `subxt::Config` to give some type information +//! that is currently not covered by the metadata. +//! +//! We now show these steps in detail. As an example we use the +//! ["Ajuna"](https://parachains.info/details/ajuna_network/) parachain that is currently (2023-06-26) +//! deployed on Polkadot and [Kusama (as "Bajun")](https://parachains.info/details/bajun_network). +//! +//! +//! ## 1. Fetch the Metadata +//! +//! To fetch the metadata for the Ajuna network, we need to have the URL of an RPC node. +//! We can find "Ajuna Network" by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/). +//! We connect to the node, which leads us to [this page](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc-parachain.ajuna.network#/explorer). +//! In the url we can already see the url of the RPC endpoint of the node. It is also printed to the Javascript console of the browser: +//! `WS endpoint= wss://rpc-parachain.ajuna.network`. +//! +//! ``` +//! subxt metadata --url ajuna_metadata.scale +//! ``` +//! +//! +//! +//! In order to connect to a //! chain we first need to fetch its metadata. This requires us to know a valid //! RPC endpoint of the chain. //! The [Substrate Chains Runtime Api Doc Center](https://substrate.rs/index.html) lists parachains diff --git a/subxt/src/config/mod.rs b/subxt/src/config/mod.rs index d94f04810d..586697902d 100644 --- a/subxt/src/config/mod.rs +++ b/subxt/src/config/mod.rs @@ -31,15 +31,15 @@ pub trait Config: 'static { /// The output of the `Hasher` function. type Hash: Debug - + Copy - + Send - + Sync - + Decode - + AsRef<[u8]> - + Serialize - + DeserializeOwned - + Encode - + PartialEq; + + Copy + + Send + + Sync + + Decode + + AsRef<[u8]> + + Serialize + + DeserializeOwned + + Encode + + PartialEq; /// The account ID type. type AccountId: Debug + Clone + Encode; @@ -51,10 +51,10 @@ pub trait Config: 'static { type Signature: Debug + Encode; /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). - type Hasher: Debug + Hasher; + type Hasher: Debug + Hasher; /// The block header. - type Header: Debug + Header + Sync + Send + DeserializeOwned; + type Header: Debug + Header + Sync + Send + DeserializeOwned; /// This type defines the extrinsic extra and additional parameters. type ExtrinsicParams: extrinsic_params::ExtrinsicParams; @@ -100,7 +100,7 @@ pub struct WithExtrinsicParams> Config - for WithExtrinsicParams +for WithExtrinsicParams { type Index = T::Index; type Hash = T::Hash; @@ -119,10 +119,10 @@ mod substrate_impls { use primitive_types::{H256, U256}; impl Header for sp_runtime::generic::Header - where - Self: Encode, - N: Copy + Into + Into + TryFrom, - H: sp_runtime::traits::Hash + Hasher, + where + Self: Encode, + N: Copy + Into + Into + TryFrom, + H: sp_runtime::traits::Hash + Hasher, { type Number = N; type Hasher = H; @@ -140,6 +140,14 @@ mod substrate_impls { } } + impl Hasher for sp_runtime::traits::BlakeTwo256 { + type Output = H256; + + fn hash(s: &[u8]) -> Self::Output { + ::hash(s) + } + } + impl Hasher for sp_core::KeccakHasher { type Output = H256; @@ -147,4 +155,12 @@ mod substrate_impls { ::hash(s) } } + + impl Hasher for sp_runtime::traits::Keccak256 { + type Output = H256; + + fn hash(s: &[u8]) -> Self::Output { + ::hash(s) + } + } } From 05aae73b2680253cfddc839440e254a3484f03c3 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Thu, 29 Jun 2023 22:01:05 +0200 Subject: [PATCH 03/28] add the 3rd config --- examples/parachain-example/src/main.rs | 155 ++++++++++++++++++++++--- 1 file changed, 138 insertions(+), 17 deletions(-) diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 10db80fdcf..752bfec4b7 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -49,6 +49,10 @@ //! Statemint (Polkadot Asset Hub) is part of the [Cumulus Github repository](https://github.com/paritytech/cumulus). //! The crate defining the parachains runtime can be found [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot). //! +//! ## 2.1 Create the config from scratch +//! +//! First we want to create the config from scratch to understand all the details. +//! //! ### AccountId, Index, Hash, Hasher and Header //! We need to check, where the parachains runtime implements the frame_system::Config trait. //! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. @@ -132,9 +136,9 @@ //! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [subxt::config::ExtrinsicParams] trait, see below. //! Now we have all the parts we need to create our config `StatemintConfig` and implment the [subxt::Config] trait on it. //! Note that StatemintConfig is an empty enum, an _uninhabited type_ that is never means to be instantiated -//! but just gives type information to various interfaces of subxt. +//! but just gives type information to various interfaces of _subxt_. //! -//! # 3. Simplifying the config +//! ## 2.2 Simplifying the config //! //! Now you should be able to create a config for a parachain from scratch and understand the details of its construction. //! However this is quite a tedious process, so subxt provides some sane defaults that can make your life easier. @@ -149,28 +153,45 @@ //! - [subxt::hash] instead of [sp_runtime::MultiAddress] //! - [subxt::config::substrate::Era] instead of [sp_runtime::generic::Era] //! - [subxt::config::substrate::SubstrateHeader] instead of [sp_runtime::generic::Header] -//! - [subxt::config::substrate::AssetTip] instead of [pallet_transaction_payment::ChargeTransactionPayment] -//! - [subxt::config::substrate::BlakeTwo256] instead of [sp_runtime::generic::Era] -//! - [subxt::config::substrate] instead of [sp_runtime::generic::Era] -//! - [subxt::config::substrate::Era] instead of [sp_runtime::generic::Era] -//! todo -use sp_core::H256; +//! - [subxt::config::substrate::AssetTip] and [subxt::config::polkadot::PlainTip] instead of [pallet_transaction_payment::ChargeTransactionPayment] +//! - [subxt::config::substrate::BlakeTwo256] instead of [sp_core::Blake2Hasher] or [sp_runtime::traits::BlakeTwo256] +//! - [subxt::config::substrate::DigestItem] and [subxt::config::substrate::Digest] instead of types from [sp_runtime::generic::digest] +//! - [subxt::config::substrate::ConsensusEngineId] instead of [sp_runtime::ConsensusEngineId] +//! +//! With these optimizations, our config can look like the `StatemintConfig2` below. +//! +//! ## 2.3. Use the Substrate default config as much as possible +//! +//! Because most substrate based chains share a great deal of types, _subxt_ already provides two configs: +//! - [subxt::SubstrateConfig] configured for the default [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) +//! - [subxt::PolkadotConfig] configured for the [polkadot node implementation](https://github.com/paritytech/polkadot) +//! +//! Even those two just differ in the type of the `Tip` and `MultiAddress`. +//! Statemint (Polkadot Asset Hub) seems to match the Polkadot config in almost all points, except for the `ExtrinsicParams`. +//! Here the tips follow the same structure as for the default substrate node. +//! We can now simply build the config for Statemint from the building blocks provided +//! by [subxt::SubstrateConfig] and [subxt::PolkadotConfig] as shown below in `StatemintConfig3`. +//! +//! All configs we constructed, `StatemintConfig`, `StatemintConfig2` and `StatemintConfig3` should behave in the same way. +//! All three ways are valid for constructing a config. Choose one depending on your use case. +//! use subxt::config::ExtrinsicParams; use subxt::{ - config::substrate::{BlakeTwo256, SubstrateHeader}, Config, OnlineClient, PolkadotConfig, SubstrateConfig, }; -use codec::{Decode, Encode}; +use codec::{Encode}; -#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +#[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct ChargeAssetTxPayment { #[codec(compact)] tip: u128, asset_id: Option, } +//////////////////////////////////////////////////////////// +// First Config (verbose and detailed) +//////////////////////////////////////////////////////////// -/// Default set of commonly used types by Polkadot nodes. pub enum StatemintConfig {} impl Config for StatemintConfig { @@ -184,20 +205,20 @@ impl Config for StatemintConfig { type ExtrinsicParams = StatemintExtrinsicParams; } -#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +#[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct StatemintExtrinsicParams { extra_params: StatemintExtraParams, additional_params: StatemintAdditionalParams, } -#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +#[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct StatemintExtraParams { era: sp_runtime::generic::Era, nonce: u32, charge: ChargeAssetTxPayment, } -#[derive(Encode, Decode, Debug, Clone, Eq, PartialEq)] +#[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct StatemintAdditionalParams { spec_version: u32, tx_version: u32, @@ -247,10 +268,110 @@ impl ExtrinsicParams<::Index, ; + type Signature = subxt::utils::MultiSignature; + type Hasher = subxt::config::substrate::BlakeTwo256; + type Header = subxt::config::substrate::SubstrateHeader; + type ExtrinsicParams = StatemintExtrinsicParams; +} + +#[derive(Encode, Debug, Clone)] +pub struct StatemintExtrinsicParams2 { + extra_params: StatemintExtraParams2, + additional_params: StatemintAdditionalParams2, +} + +#[derive(Encode, Debug, Clone)] +pub struct StatemintExtraParams2 { + era: subxt::config::extrinsic_params::Era, + nonce: u32, + charge: subxt::config::substrate::AssetTip, +} + +#[derive(Encode, Debug, Clone)] +pub struct StatemintAdditionalParams2 { + spec_version: u32, + tx_version: u32, + genesis_hash: subxt::utils::H256, + mortality_hash: subxt::utils::H256, +} + +impl ExtrinsicParams<::Index, ::Hash> +for StatemintExtrinsicParams2 +{ + /// mortality hash, era, charge + type OtherParams = ( + subxt::utils::H256, + subxt::config::extrinsic_params::Era, + subxt::config::substrate::AssetTip, + ); + + fn new( + spec_version: u32, + tx_version: u32, + nonce: ::Index, + genesis_hash: ::Hash, + other_params: Self::OtherParams, + ) -> Self { + let (mortality_hash, era, charge) = other_params; + + let extra_params = StatemintExtraParams2 { era, nonce, charge }; + + let additional_params = StatemintAdditionalParams2 { + spec_version, + tx_version, + genesis_hash, + mortality_hash, + }; + Self { + extra_params, + additional_params, + } + } + + fn encode_extra_to(&self, v: &mut Vec) { + self.extra_params.encode_to(v); + } + + fn encode_additional_to(&self, v: &mut Vec) { + self.additional_params.encode_to(v); + } +} + +//////////////////////////////////////////////////////////// +// Third Config (using the Substrate and Polkadot Config) +//////////////////////////////////////////////////////////// + +pub enum StatemintConfig3 {} + +impl Config for StatemintConfig3 { + type Index = ::Index; + type Hash = ::Hash; + type AccountId = ::AccountId; + type Address = ::Address; + type Signature = ::Signature; + type Hasher = ::Hasher; + type Header = ::Header; + // this is the only difference: + type ExtrinsicParams = ::ExtrinsicParams; +} + + +/// In this example you can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. #[tokio::main] async fn main() -> Result<(), Box> { - // // Create a new API client, configured to talk to Polkadot nodes. - // let api = OnlineClient::::new().await?; + let rpc_endpoint = todo!(); + let api = OnlineClient::::from_url().await?; println!("Hello"); Ok(()) From e8dea9888f4677e97dd871eb2d166188a8b2a6de Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Fri, 30 Jun 2023 09:55:03 +0200 Subject: [PATCH 04/28] subscribe to block with configs --- examples/parachain-example/Cargo.toml | 5 +-- examples/parachain-example/src/main.rs | 51 +++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/examples/parachain-example/Cargo.toml b/examples/parachain-example/Cargo.toml index 945655df9d..c0adfd6975 100644 --- a/examples/parachain-example/Cargo.toml +++ b/examples/parachain-example/Cargo.toml @@ -15,7 +15,4 @@ sp-core = "21.0.0" sp-runtime = "24.0.0" codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } scale-decode = "0.7.0" -scale-encode = "0.3.0" -#pallet-asset-tx-payment = "21.0.0" - -#asset-hub-polkadot-runtime = { git = "https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot" } +scale-encode = "0.3.0" \ No newline at end of file diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 752bfec4b7..99ee7d1f38 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -11,7 +11,6 @@ //! ["Statemint"](https://parachains.info/details/statemint) parachain, also known as "Asset Hub" that is currently (2023-06-26) //! deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). //! -//! //! ## 1. Fetch the Metadata //! //! To fetch the metadata for the Statemint parachain, we need to have the URL of an RPC node. @@ -179,7 +178,7 @@ use subxt::config::ExtrinsicParams; use subxt::{ Config, OnlineClient, PolkadotConfig, SubstrateConfig, }; - +use futures::StreamExt; use codec::{Encode}; #[derive(Encode, Debug, Clone, Eq, PartialEq)] @@ -188,6 +187,7 @@ pub struct ChargeAssetTxPayment { tip: u128, asset_id: Option, } + //////////////////////////////////////////////////////////// // First Config (verbose and detailed) //////////////////////////////////////////////////////////// @@ -370,9 +370,50 @@ impl Config for StatemintConfig3 { /// In this example you can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. #[tokio::main] async fn main() -> Result<(), Box> { - let rpc_endpoint = todo!(); - let api = OnlineClient::::from_url().await?; + let rpc_endpoint = "wss://polkadot-asset-hub-rpc.polkadot.io:443"; + + // here we use the config: + let api = OnlineClient::::from_url(rpc_endpoint).await?; + + // Subscribe to all finalized blocks: + let mut blocks_sub = api.blocks().subscribe_finalized().await?; + + // For each block, print a bunch of information about it: + while let Some(block) = blocks_sub.next().await { + let block = block?; + + let block_number = block.header().number; + let block_hash = block.hash(); + + println!("Block #{block_number}:"); + println!(" Hash: {block_hash}"); + println!(" Extrinsics:"); + + let body = block.body().await?; + for ext in body.extrinsics().iter() { + let ext = ext?; + let idx = ext.index(); + let events = ext.events().await?; + // here we make use of the generated metadata code: + let decoded_ext = ext.as_root_extrinsic::(); + + println!(" Extrinsic #{idx}:"); + println!(" Bytes: {}", ext.bytes().len()); + println!(" Decoded: {decoded_ext:?}"); + println!(" Events:"); + + for evt in events.iter() { + let evt = evt?; + + let pallet_name = evt.pallet_name(); + let event_name = evt.variant_name(); + let event_values = evt.field_values()?; + + println!(" {pallet_name}_{event_name}"); + println!(" {}", event_values); + } + } + } - println!("Hello"); Ok(()) } From 4466f81430866fb971bb49c61c77043bef48d0c0 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Fri, 30 Jun 2023 10:05:39 +0200 Subject: [PATCH 05/28] delete table file --- examples/parachain-example/src/main.rs | 11 +++----- examples/parachain-example/table.md | 10 -------- subxt/examples/connect_to_a_parachain.rs | 1 - subxt/src/config/mod.rs | 32 ++++++++++++------------ 4 files changed, 20 insertions(+), 34 deletions(-) delete mode 100644 examples/parachain-example/table.md diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 99ee7d1f38..0e92cfbe7d 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -174,12 +174,10 @@ //! All configs we constructed, `StatemintConfig`, `StatemintConfig2` and `StatemintConfig3` should behave in the same way. //! All three ways are valid for constructing a config. Choose one depending on your use case. //! -use subxt::config::ExtrinsicParams; -use subxt::{ - Config, OnlineClient, PolkadotConfig, SubstrateConfig, -}; +use codec::Encode; use futures::StreamExt; -use codec::{Encode}; +use subxt::config::ExtrinsicParams; +use subxt::{Config, OnlineClient, PolkadotConfig, SubstrateConfig}; #[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct ChargeAssetTxPayment { @@ -307,7 +305,7 @@ pub struct StatemintAdditionalParams2 { } impl ExtrinsicParams<::Index, ::Hash> -for StatemintExtrinsicParams2 + for StatemintExtrinsicParams2 { /// mortality hash, era, charge type OtherParams = ( @@ -366,7 +364,6 @@ impl Config for StatemintConfig3 { type ExtrinsicParams = ::ExtrinsicParams; } - /// In this example you can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. #[tokio::main] async fn main() -> Result<(), Box> { diff --git a/examples/parachain-example/table.md b/examples/parachain-example/table.md deleted file mode 100644 index 18b4aefffe..0000000000 --- a/examples/parachain-example/table.md +++ /dev/null @@ -1,10 +0,0 @@ -| Tuple element | encoded type of struct | encoded type of `AdditionalSigned` type. | -| ------------------------------------ | ----------------------------------------------- | ---------------------------------------- | -| [frame_system::CheckNonZeroSender] | () | () | -| [frame_system::CheckSpecVersion] | () | [u32] | -| [frame_system::CheckTxVersion] | () | [u32] | -| [frame_system::CheckGenesis] | () | `Config::Hash` = | -| [frame_system::CheckMortality] | [sp_runtime::generic::era::Era] | `Config::Hash` = [sp_core::H256] | -| [frame_system::CheckNonce] | [Config::Index] = [u32] | () | -| [frame_system::CheckWeight] | () | () | -| [frame_system::ChargeAssetTxPayment] | [pallet_asset_tx_payment::ChargeAssetTxPayment] | () | diff --git a/subxt/examples/connect_to_a_parachain.rs b/subxt/examples/connect_to_a_parachain.rs index 90bf150c14..7f405a8b5a 100644 --- a/subxt/examples/connect_to_a_parachain.rs +++ b/subxt/examples/connect_to_a_parachain.rs @@ -52,7 +52,6 @@ use subxt::{Config, OnlineClient, PolkadotConfig, SubstrateConfig}; - /// Default set of commonly used types by Polkadot nodes. pub enum AjunaConfig {} diff --git a/subxt/src/config/mod.rs b/subxt/src/config/mod.rs index 586697902d..436d2213cf 100644 --- a/subxt/src/config/mod.rs +++ b/subxt/src/config/mod.rs @@ -31,15 +31,15 @@ pub trait Config: 'static { /// The output of the `Hasher` function. type Hash: Debug - + Copy - + Send - + Sync - + Decode - + AsRef<[u8]> - + Serialize - + DeserializeOwned - + Encode - + PartialEq; + + Copy + + Send + + Sync + + Decode + + AsRef<[u8]> + + Serialize + + DeserializeOwned + + Encode + + PartialEq; /// The account ID type. type AccountId: Debug + Clone + Encode; @@ -51,10 +51,10 @@ pub trait Config: 'static { type Signature: Debug + Encode; /// The hashing system (algorithm) being used in the runtime (e.g. Blake2). - type Hasher: Debug + Hasher; + type Hasher: Debug + Hasher; /// The block header. - type Header: Debug + Header + Sync + Send + DeserializeOwned; + type Header: Debug + Header + Sync + Send + DeserializeOwned; /// This type defines the extrinsic extra and additional parameters. type ExtrinsicParams: extrinsic_params::ExtrinsicParams; @@ -100,7 +100,7 @@ pub struct WithExtrinsicParams> Config -for WithExtrinsicParams + for WithExtrinsicParams { type Index = T::Index; type Hash = T::Hash; @@ -119,10 +119,10 @@ mod substrate_impls { use primitive_types::{H256, U256}; impl Header for sp_runtime::generic::Header - where - Self: Encode, - N: Copy + Into + Into + TryFrom, - H: sp_runtime::traits::Hash + Hasher, + where + Self: Encode, + N: Copy + Into + Into + TryFrom, + H: sp_runtime::traits::Hash + Hasher, { type Number = N; type Hasher = H; From 2c5918c2481e93c92960dc34fa2c10c1c9100ebc Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Fri, 30 Jun 2023 10:10:39 +0200 Subject: [PATCH 06/28] spaces instead of tabs --- examples/parachain-example/src/main.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 0e92cfbe7d..7326ea9e46 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -85,14 +85,14 @@ //! //! ```rs //! pub type SignedExtra = ( -//! frame_system::CheckNonZeroSender, -//! frame_system::CheckSpecVersion, -//! frame_system::CheckTxVersion, -//! frame_system::CheckGenesis, -//! frame_system::CheckEra, -//! frame_system::CheckNonce, -//! frame_system::CheckWeight, -//! pallet_asset_tx_payment::ChargeAssetTxPayment, +//! frame_system::CheckNonZeroSender, +//! frame_system::CheckSpecVersion, +//! frame_system::CheckTxVersion, +//! frame_system::CheckGenesis, +//! frame_system::CheckEra, +//! frame_system::CheckNonce, +//! frame_system::CheckWeight, +//! pallet_asset_tx_payment::ChargeAssetTxPayment, //! ); //! ``` //! From 0b23e2523f34f2a5710566dd7d1da9c72ec01093 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Fri, 30 Jun 2023 10:14:06 +0200 Subject: [PATCH 07/28] remove original ajuna example --- subxt/examples/connect_to_a_parachain.rs | 75 ------------------------ 1 file changed, 75 deletions(-) delete mode 100644 subxt/examples/connect_to_a_parachain.rs diff --git a/subxt/examples/connect_to_a_parachain.rs b/subxt/examples/connect_to_a_parachain.rs deleted file mode 100644 index 7f405a8b5a..0000000000 --- a/subxt/examples/connect_to_a_parachain.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! # Connecting to a parachain with Subxt -//! -//! In this example we connect to a parachain and subscribe to its blocks. -//! There are many parachains on Polkadot and Kusama. Connecting to a parachain (or any other substrate based blockchain) with subxt requires 2 steps: -//! -//! 1. Fetching the chains metadata to generate a static interface via the subxt codegen. -//! 2. Creating a config struct that implements `subxt::Config` to give some type information -//! that is currently not covered by the metadata. -//! -//! We now show these steps in detail. As an example we use the -//! ["Ajuna"](https://parachains.info/details/ajuna_network/) parachain that is currently (2023-06-26) -//! deployed on Polkadot and [Kusama (as "Bajun")](https://parachains.info/details/bajun_network). -//! -//! -//! ## 1. Fetch the Metadata -//! -//! To fetch the metadata for the Ajuna network, we need to have the URL of an RPC node. -//! We can find "Ajuna Network" by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/). -//! We connect to the node, which leads us to [this page](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc-parachain.ajuna.network#/explorer). -//! In the url we can already see the url of the RPC endpoint of the node. It is also printed to the Javascript console of the browser: -//! `WS endpoint= wss://rpc-parachain.ajuna.network`. -//! -//! ``` -//! subxt metadata --url ajuna_metadata.scale -//! ``` -//! -//! -//! -//! In order to connect to a -//! chain we first need to fetch its metadata. This requires us to know a valid -//! RPC endpoint of the chain. -//! The [Substrate Chains Runtime Api Doc Center](https://substrate.rs/index.html) lists parachains -//! on Polkadot and Kusama and gives us a list of RPC endpoints for each parachain. Alternatively -//! we can also look for the RPC endpoint of a chain via [Polkadot.js](https://polkadot.js.org/apps/). -//! In the side menu, you can select a Polkadot/Kusama parachain. The hit the "Switch" button and -//! let the page load the chains data. The RPC endpoint url can be found as part of the url. -//! You can also open the console, to see the RPC endpoint url printed without URL-encoded special characters. -//! -//! Let's go through an example for the "Ajuna" parachain on Polkadot. -//! Selecting it in the [Polkadot.js](https://polkadot.js.org/apps/) menu, then opening the console -//! lets us observe the following output: `WS endpoint= wss://rpc-parachain.ajuna.network` -//! -//! We can now get the metadata of the chain via the subxt-cli tool. -//! It is important to note that we need to add a `:433` as the port number here: -//! ```txt -//! metadata --url wss://rpc-parachain.ajuna.network:443 > artifacts/ajuna_metadata.scale -//! ``` -//! -//! This allows us to construct a module with the ajuna types, calls, -//! -//! - -use subxt::{Config, OnlineClient, PolkadotConfig, SubstrateConfig}; - -/// Default set of commonly used types by Polkadot nodes. -pub enum AjunaConfig {} - -impl Config for AjunaConfig { - type Index = ::Index; - type Hash = ::Hash; - type AccountId = ::AccountId; - type Address = ::Address; - type Signature = ::Signature; - type Hasher = ::Hasher; - type Header = ::Header; - type ExtrinsicParams = ::ExtrinsicParams; -} - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Create a new API client, configured to talk to Polkadot nodes. - let api = OnlineClient::::new().await?; - - Ok(()) -} From d6d0c7970f645b147372d890f02031fe4b25f84f Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Wed, 5 Jul 2023 14:41:07 +0200 Subject: [PATCH 08/28] zombienet setup --- .../asset-hub-zombienet.toml | 25 ++++++++ .../parachain-example/src/bin/fetch_blocks.rs | 60 ++++++++++++++++++ .../src/bin/submit_transaction.rs | 61 +++++++++++++++++++ .../parachain-example/src/{main.rs => lib.rs} | 55 ++--------------- 4 files changed, 150 insertions(+), 51 deletions(-) create mode 100644 examples/parachain-example/asset-hub-zombienet.toml create mode 100644 examples/parachain-example/src/bin/fetch_blocks.rs create mode 100644 examples/parachain-example/src/bin/submit_transaction.rs rename examples/parachain-example/src/{main.rs => lib.rs} (91%) diff --git a/examples/parachain-example/asset-hub-zombienet.toml b/examples/parachain-example/asset-hub-zombienet.toml new file mode 100644 index 0000000000..34f7c7d4df --- /dev/null +++ b/examples/parachain-example/asset-hub-zombienet.toml @@ -0,0 +1,25 @@ +[relaychain] +default_image = "docker.io/parity/polkadot:latest" +default_command = "polkadot" +default_args = [ "-lparachain=debug" ] + +chain = "kusama-local" + + [[relaychain.nodes]] + name = "alice" + validator = true + + [[relaychain.nodes]] + name = "bob" + validator = true + +[[parachains]] +id = 100 +chain = "asset-hub-kusama-local" + + [parachains.collator] + name = "collator01" + image = "docker.io/parity/polkadot-parachain:latest" + command = "polkadot-parachain" + args = ["-lparachain=debug"] + \ No newline at end of file diff --git a/examples/parachain-example/src/bin/fetch_blocks.rs b/examples/parachain-example/src/bin/fetch_blocks.rs new file mode 100644 index 0000000000..3b6546ec2d --- /dev/null +++ b/examples/parachain-example/src/bin/fetch_blocks.rs @@ -0,0 +1,60 @@ +use futures::StreamExt; +use subxt::OnlineClient; +use parachain_example::StatemintConfig; + +/// In this example we connect to the official polkadot asset hub parachain and subscribe to blocks that get produced. +/// You can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. +/// +/// To run this example: +/// ```txt +/// cargo run --bin fetch_blocks +/// ``` +#[tokio::main] +async fn main() -> Result<(), Box> { + let rpc_endpoint = "wss://polkadot-asset-hub-rpc.polkadot.io:443"; + + // here we use the config: + let api = OnlineClient::::from_url(rpc_endpoint).await?; + + // Subscribe to all finalized blocks: + let mut blocks_sub = api.blocks().subscribe_finalized().await?; + + // For each block, print a bunch of information about it: + while let Some(block) = blocks_sub.next().await { + let block = block?; + + let block_number = block.header().number; + let block_hash = block.hash(); + + println!("Block #{block_number}:"); + println!(" Hash: {block_hash}"); + println!(" Extrinsics:"); + + let body = block.body().await?; + for ext in body.extrinsics().iter() { + let ext = ext?; + let idx = ext.index(); + let events = ext.events().await?; + // here we make use of the generated metadata code: + let decoded_ext = ext.as_root_extrinsic::(); + + println!(" Extrinsic #{idx}:"); + println!(" Bytes: {}", ext.bytes().len()); + println!(" Decoded: {decoded_ext:?}"); + println!(" Events:"); + + for evt in events.iter() { + let evt = evt?; + + let pallet_name = evt.pallet_name(); + let event_name = evt.variant_name(); + let event_values = evt.field_values()?; + + println!(" {pallet_name}_{event_name}"); + println!(" {}", event_values); + } + } + } + + Ok(()) +} diff --git a/examples/parachain-example/src/bin/submit_transaction.rs b/examples/parachain-example/src/bin/submit_transaction.rs new file mode 100644 index 0000000000..6e55ddbde3 --- /dev/null +++ b/examples/parachain-example/src/bin/submit_transaction.rs @@ -0,0 +1,61 @@ +/// In this example we want to submit a transaction to the asset hub parachain. +/// Doing so on the official polkadot network, would require us to have an account with sufficient funds. +/// That is why we spawn a local asset hub parachain instead, that comes with pre-funded dev accounts. +/// +/// # Setting up the local parachain +/// +/// We use [zombienet](https://github.com/paritytech/zombienet) to start up a local asset hub. +/// +/// ## 1. Install necessary tools +/// +/// To setup the local parachain we need to have 3 binaries installed in our path: +/// +/// ### 1. `zombienet` +/// +/// Zombienet is a tool for quickly spinning up a (local) blockchain network. Please follow the install guide in the [zombienet github repo](https://github.com/paritytech/zombienet). +/// +/// ### 2. `polkadot` +/// +/// Build the polkadot binary from the [polkadot github repo](https://github.com/paritytech/polkadot) and install it in your path: +/// ```txt +/// git clone https://github.com/paritytech/polkadot.git +/// cd polkadot +/// cargo build --release +/// cargo install --path . +/// ``` +/// +/// ### 3. `polkadot-parachain` +/// +/// The polkadot asset hub is part of the [cumulus github repo](https://github.com/paritytech/cumulus), an SDK for developing parachains. +/// Building the cumulus workspace produces a binary called `polkadot-parachain` that has the capability and configuration data to run the asset hub. +/// ```txt +/// git clone https://github.com/paritytech/cumulus.git +/// cd cumulus +/// cargo build --release +/// cargo install --path . +/// ``` +/// +/// ## 2. Run the parachain locally +/// +/// Zombienet can now spawn the parachain locally from a configuration file, `asset-hub-zombienet.toml` in this case. +/// We need to have at least 2 validator nodes running (via the `polkadot` binary), +/// while the `polkadot-parachain` binary starts the asset hub parachain and gets it registered with the validator nodes. +/// To do that, run: +/// ```txt +/// zombienet -p native spawn asset-hub-zombienet.toml +/// ``` +/// Zombienet uses Kubernetes by default, but we can use it without Kubernetes, by providing the `-p native` flag. +/// +/// # Running the example +/// +/// After you have the network running, you should see [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:41955#/explorer] +/// as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. +/// +/// To run this example: +/// ```txt +/// cargo run --bin submit_transaction +/// ``` +#[tokio::main] +pub async fn main() { + todo!() +} diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/lib.rs similarity index 91% rename from examples/parachain-example/src/main.rs rename to examples/parachain-example/src/lib.rs index 7326ea9e46..e07670ab84 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/lib.rs @@ -173,6 +173,10 @@ //! //! All configs we constructed, `StatemintConfig`, `StatemintConfig2` and `StatemintConfig3` should behave in the same way. //! All three ways are valid for constructing a config. Choose one depending on your use case. +//! +//! # 3 Try the examples +//! We have two examples of interacting with the parachain, that you can try. You find them in the bin directory of this crate. Please check them out. +//! //! use codec::Encode; use futures::StreamExt; @@ -363,54 +367,3 @@ impl Config for StatemintConfig3 { // this is the only difference: type ExtrinsicParams = ::ExtrinsicParams; } - -/// In this example you can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. -#[tokio::main] -async fn main() -> Result<(), Box> { - let rpc_endpoint = "wss://polkadot-asset-hub-rpc.polkadot.io:443"; - - // here we use the config: - let api = OnlineClient::::from_url(rpc_endpoint).await?; - - // Subscribe to all finalized blocks: - let mut blocks_sub = api.blocks().subscribe_finalized().await?; - - // For each block, print a bunch of information about it: - while let Some(block) = blocks_sub.next().await { - let block = block?; - - let block_number = block.header().number; - let block_hash = block.hash(); - - println!("Block #{block_number}:"); - println!(" Hash: {block_hash}"); - println!(" Extrinsics:"); - - let body = block.body().await?; - for ext in body.extrinsics().iter() { - let ext = ext?; - let idx = ext.index(); - let events = ext.events().await?; - // here we make use of the generated metadata code: - let decoded_ext = ext.as_root_extrinsic::(); - - println!(" Extrinsic #{idx}:"); - println!(" Bytes: {}", ext.bytes().len()); - println!(" Decoded: {decoded_ext:?}"); - println!(" Events:"); - - for evt in events.iter() { - let evt = evt?; - - let pallet_name = evt.pallet_name(); - let event_name = evt.variant_name(); - let event_values = evt.field_values()?; - - println!(" {pallet_name}_{event_name}"); - println!(" {}", event_values); - } - } - } - - Ok(()) -} From 4a632f1113f548529cb1be6bb0f16d0f9913d0e3 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Thu, 6 Jul 2023 12:11:03 +0200 Subject: [PATCH 09/28] nft minting example --- examples/parachain-example/Cargo.lock | 111 +++++++++- examples/parachain-example/Cargo.toml | 1 + .../asset-hub-zombienet.toml | 4 +- .../parachain-example/src/bin/fetch_blocks.rs | 17 +- .../src/bin/submit_transaction.rs | 201 +++++++++++++----- examples/parachain-example/src/lib.rs | 7 +- 6 files changed, 266 insertions(+), 75 deletions(-) diff --git a/examples/parachain-example/Cargo.lock b/examples/parachain-example/Cargo.lock index c0ee2db56c..075412ba4a 100644 --- a/examples/parachain-example/Cargo.lock +++ b/examples/parachain-example/Cargo.lock @@ -190,6 +190,23 @@ dependencies = [ "serde", ] +[[package]] +name = "bip39" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +dependencies = [ + "bitcoin_hashes", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + [[package]] name = "bitflags" version = "1.3.2" @@ -459,6 +476,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + [[package]] name = "darling" version = "0.14.4" @@ -1464,6 +1494,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + [[package]] name = "metadata" version = "0.1.0" @@ -1574,6 +1616,7 @@ dependencies = [ "sp-core", "sp-runtime", "subxt", + "subxt-signer", "tokio", ] @@ -1651,6 +1694,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "pbkdf2" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "percent-encoding" version = "2.3.0" @@ -2156,7 +2208,7 @@ dependencies = [ "arrayvec 0.5.2", "curve25519-dalek 2.1.3", "getrandom 0.1.16", - "merlin", + "merlin 2.0.1", "rand 0.7.3", "rand_core 0.5.1", "sha2 0.8.2", @@ -2164,6 +2216,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "schnorrkel" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "844b7645371e6ecdf61ff246ba1958c29e802881a749ae3fb1993675d210d28d" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "curve25519-dalek-ng", + "merlin 3.0.0", + "rand_core 0.6.4", + "serde_bytes", + "sha2 0.9.9", + "subtle-ng", + "zeroize", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2239,6 +2308,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c5113243e4a3a1c96587342d067f3e6b0f50790b6cf40d2868eb647a3eef0e" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.164" @@ -2424,7 +2502,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log", - "merlin", + "merlin 2.0.1", "parity-scale-codec", "parking_lot", "paste", @@ -2432,7 +2510,7 @@ dependencies = [ "rand 0.8.5", "regex", "scale-info", - "schnorrkel", + "schnorrkel 0.9.1", "secp256k1", "secrecy", "serde", @@ -2749,7 +2827,7 @@ checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" dependencies = [ "hmac 0.11.0", "pbkdf2 0.8.0", - "schnorrkel", + "schnorrkel 0.9.1", "sha2 0.9.9", "zeroize", ] @@ -2760,6 +2838,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "subxt" version = "0.29.0" @@ -2830,6 +2914,25 @@ dependencies = [ "thiserror", ] +[[package]] +name = "subxt-signer" +version = "0.29.0" +dependencies = [ + "bip39", + "hex", + "hmac 0.12.1", + "parity-scale-codec", + "pbkdf2 0.12.1", + "regex", + "schnorrkel 0.10.2", + "secrecy", + "sha2 0.10.7", + "sp-core-hashing", + "subxt", + "thiserror", + "zeroize", +] + [[package]] name = "syn" version = "1.0.109" diff --git a/examples/parachain-example/Cargo.toml b/examples/parachain-example/Cargo.toml index c0adfd6975..0704b78e50 100644 --- a/examples/parachain-example/Cargo.toml +++ b/examples/parachain-example/Cargo.toml @@ -8,6 +8,7 @@ members = ["./metadata"] [dependencies] subxt = { path = "../../subxt" } +subxt-signer = { path = "../../signer", features=["subxt"] } futures = { version = "0.3.27", default-features = false, features = ["std"] } tokio = { version = "1.28", features = ["macros", "time", "rt-multi-thread"] } metadata = { path = "./metadata" } diff --git a/examples/parachain-example/asset-hub-zombienet.toml b/examples/parachain-example/asset-hub-zombienet.toml index 34f7c7d4df..89bfaf0570 100644 --- a/examples/parachain-example/asset-hub-zombienet.toml +++ b/examples/parachain-example/asset-hub-zombienet.toml @@ -3,7 +3,7 @@ default_image = "docker.io/parity/polkadot:latest" default_command = "polkadot" default_args = [ "-lparachain=debug" ] -chain = "kusama-local" +chain = "rococo-local" [[relaychain.nodes]] name = "alice" @@ -15,7 +15,7 @@ chain = "kusama-local" [[parachains]] id = 100 -chain = "asset-hub-kusama-local" +chain = "asset-hub-polkadot-local" [parachains.collator] name = "collator01" diff --git a/examples/parachain-example/src/bin/fetch_blocks.rs b/examples/parachain-example/src/bin/fetch_blocks.rs index 3b6546ec2d..b32dedf8f3 100644 --- a/examples/parachain-example/src/bin/fetch_blocks.rs +++ b/examples/parachain-example/src/bin/fetch_blocks.rs @@ -1,14 +1,16 @@ +//! In this example we connect to the official polkadot asset hub parachain and subscribe to blocks that get produced. +//! You can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. +//! +//! To run this example: +//! ```txt +//! cargo run --bin fetch_blocks +//! ``` + use futures::StreamExt; -use subxt::OnlineClient; use parachain_example::StatemintConfig; +use subxt::OnlineClient; -/// In this example we connect to the official polkadot asset hub parachain and subscribe to blocks that get produced. -/// You can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. -/// -/// To run this example: -/// ```txt /// cargo run --bin fetch_blocks -/// ``` #[tokio::main] async fn main() -> Result<(), Box> { let rpc_endpoint = "wss://polkadot-asset-hub-rpc.polkadot.io:443"; @@ -35,6 +37,7 @@ async fn main() -> Result<(), Box> { let ext = ext?; let idx = ext.index(); let events = ext.events().await?; + // here we make use of the generated metadata code: let decoded_ext = ext.as_root_extrinsic::(); diff --git a/examples/parachain-example/src/bin/submit_transaction.rs b/examples/parachain-example/src/bin/submit_transaction.rs index 6e55ddbde3..003d7c353d 100644 --- a/examples/parachain-example/src/bin/submit_transaction.rs +++ b/examples/parachain-example/src/bin/submit_transaction.rs @@ -1,61 +1,146 @@ -/// In this example we want to submit a transaction to the asset hub parachain. -/// Doing so on the official polkadot network, would require us to have an account with sufficient funds. -/// That is why we spawn a local asset hub parachain instead, that comes with pre-funded dev accounts. -/// -/// # Setting up the local parachain -/// -/// We use [zombienet](https://github.com/paritytech/zombienet) to start up a local asset hub. -/// -/// ## 1. Install necessary tools -/// -/// To setup the local parachain we need to have 3 binaries installed in our path: -/// -/// ### 1. `zombienet` -/// -/// Zombienet is a tool for quickly spinning up a (local) blockchain network. Please follow the install guide in the [zombienet github repo](https://github.com/paritytech/zombienet). -/// -/// ### 2. `polkadot` -/// -/// Build the polkadot binary from the [polkadot github repo](https://github.com/paritytech/polkadot) and install it in your path: -/// ```txt -/// git clone https://github.com/paritytech/polkadot.git -/// cd polkadot -/// cargo build --release -/// cargo install --path . -/// ``` -/// -/// ### 3. `polkadot-parachain` -/// -/// The polkadot asset hub is part of the [cumulus github repo](https://github.com/paritytech/cumulus), an SDK for developing parachains. -/// Building the cumulus workspace produces a binary called `polkadot-parachain` that has the capability and configuration data to run the asset hub. -/// ```txt -/// git clone https://github.com/paritytech/cumulus.git -/// cd cumulus -/// cargo build --release -/// cargo install --path . -/// ``` -/// -/// ## 2. Run the parachain locally -/// -/// Zombienet can now spawn the parachain locally from a configuration file, `asset-hub-zombienet.toml` in this case. -/// We need to have at least 2 validator nodes running (via the `polkadot` binary), -/// while the `polkadot-parachain` binary starts the asset hub parachain and gets it registered with the validator nodes. -/// To do that, run: -/// ```txt -/// zombienet -p native spawn asset-hub-zombienet.toml -/// ``` -/// Zombienet uses Kubernetes by default, but we can use it without Kubernetes, by providing the `-p native` flag. -/// -/// # Running the example -/// -/// After you have the network running, you should see [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:41955#/explorer] -/// as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. -/// -/// To run this example: -/// ```txt -/// cargo run --bin submit_transaction -/// ``` +//! In this example we want to submit a transaction to the asset hub parachain. +//! Doing so on the official polkadot network, would require us to have an account with sufficient funds. +//! That is why we spawn a local asset hub parachain instead, that comes with pre-funded dev accounts. +//! +//! # Setting up the local parachain +//! +//! We use [zombienet](https://github.com/paritytech/zombienet) to start up a local asset hub. +//! +//! ## 1. Install necessary tools +//! +//! To setup the local parachain we need to have 3 binaries installed in our path: +//! +//! ### 1. `zombienet` +//! +//! Zombienet is a tool for quickly spinning up a (local) blockchain network. Please follow the install guide in the [zombienet github repo](https://github.com/paritytech/zombienet). +//! +//! ### 2. `polkadot` +//! +//! Build the polkadot binary from the [polkadot github repo](https://github.com/paritytech/polkadot) and install it in your path: +//! ```txt +//! git clone https://github.com/paritytech/polkadot.git +//! cd polkadot +//! cargo build --release +//! cargo install --path . +//! ``` +//! +//! ### 3. `polkadot-parachain` +//! +//! The polkadot asset hub is part of the [cumulus github repo](https://github.com/paritytech/cumulus), an SDK for developing parachains. +//! Building the cumulus workspace produces a binary called `polkadot-parachain` that has the capability and configuration data to run the asset hub. +//! ```txt +//! git clone https://github.com/paritytech/cumulus.git +//! cd cumulus +//! cargo build --release +//! cargo install --path . +//! ``` +//! +//! ## 2. Run the parachain locally +//! +//! Zombienet can now spawn the parachain locally from a configuration file, `asset-hub-zombienet.toml` in this case. +//! We need to have at least 2 validator nodes running (via the `polkadot` binary), +//! while the `polkadot-parachain` binary starts the asset hub parachain and gets it registered with the validator nodes. +//! To do that, run: +//! ```txt +//! zombienet -p native spawn asset-hub-zombienet.toml +//! ``` +//! Zombienet uses Kubernetes by default, but we can use it without Kubernetes, by providing the `-p native` flag. +//! +//! You might have notices, that we use `chain = "rococo-local"` in the `asset-hub-zombienet.toml` file for the relay chain. +//! This is just to make the epoch time shorter and should have no effect on your interactions with the parachain. +//! Polkadot / Kusama / Rococo have different epoch times of `24h` / `2h` / `2min` respectively. +//! The parachain is only registered after the first epoch. So we need to wait 2 minutes, until the parachain becomes interactive and produces blocks. +//! +//! +//! # Running the example +//! +//! After you have the network running, you should see something like [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:41955#/explorer] +//! as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. Here `41955` refers to the port, +//! which we will need shortly. +//! +//! In this example we use the _uniques_ pallet of the polakdot asset hub parachain. +//! The dev account _alice_ creates an NFT collection, then mints an NFT that is part of the collection. +//! Beware that this example can take up to a minute to run. Specify the port like so: +//! ```txt +//! cargo run --bin submit_transaction +//! ``` +//! + +use metadata::statemint; +use parachain_example::StatemintConfig3; +use subxt::{ + utils::{AccountId32, MultiAddress}, + OnlineClient, +}; + +use subxt_signer::sr25519::dev::{self}; + +/// cargo run --bin submit_transaction #[tokio::main] pub async fn main() { - todo!() + if let Err(err) = run().await { + eprintln!("{err}"); + } +} + +async fn run() -> Result<(), Box> { + let port = std::env::args().nth(1).expect("port must be specified"); + // Connecting to the local parachain. You might need to replace the port in `"ws://127.0.0.1:36317"` + // with a different value, depending on what your zombienet cli outputs to you. + let api = + OnlineClient::::from_url(format!("ws://127.0.0.1:{}", port)).await?; + println!("Connection with parachain established."); + let alice: MultiAddress = dev::alice().public_key().into(); + let alice_pair_signer = dev::alice(); + + const COLLECTION_ID: u32 = 12; + const NTF_ID: u32 = 234; + + // create a collection with id `42` + let collection_creation_tx = statemint::tx() + .uniques() + .create(COLLECTION_ID, alice.clone()); + let _collection_creation_events = api + .tx() + .sign_and_submit_then_watch_default(&collection_creation_tx, &alice_pair_signer) + .await + .map(|e| { + println!("Collection creation submitted, waiting for transaction to be finalized..."); + e + })? + .wait_for_finalized_success() + .await?; + println!("Collection created."); + + // create an nft in that collection with id `420` + let nft_creation_tx = statemint::tx() + .uniques() + .mint(COLLECTION_ID, NTF_ID, alice.clone()); + let _nft_creation_events = api + .tx() + .sign_and_submit_then_watch_default(&nft_creation_tx, &alice_pair_signer) + .await + .map(|e| { + println!("NFT creation submitted, waiting for transaction to be finalized..."); + e + })? + .wait_for_finalized_success() + .await?; + println!("NFT created."); + + // check in storage, that alice is the official owner of the NFT: + let nft_owner_storage_query = statemint::storage().uniques().asset(COLLECTION_ID, NTF_ID); + let nft_storage_details = api + .storage() + .at_latest() + .await? + .fetch(&nft_owner_storage_query) + .await? + .ok_or("The NFT should have an owner (alice)")?; + + // make sure that alice is the owner of the NFT: + assert_eq!(nft_storage_details.owner, dev::alice().public_key().into()); + println!("Storage Item Details: {:?}", nft_storage_details); + + Ok(()) } diff --git a/examples/parachain-example/src/lib.rs b/examples/parachain-example/src/lib.rs index e07670ab84..63f9469213 100644 --- a/examples/parachain-example/src/lib.rs +++ b/examples/parachain-example/src/lib.rs @@ -173,15 +173,14 @@ //! //! All configs we constructed, `StatemintConfig`, `StatemintConfig2` and `StatemintConfig3` should behave in the same way. //! All three ways are valid for constructing a config. Choose one depending on your use case. -//! +//! //! # 3 Try the examples //! We have two examples of interacting with the parachain, that you can try. You find them in the bin directory of this crate. Please check them out. -//! +//! //! use codec::Encode; -use futures::StreamExt; use subxt::config::ExtrinsicParams; -use subxt::{Config, OnlineClient, PolkadotConfig, SubstrateConfig}; +use subxt::{Config, PolkadotConfig, SubstrateConfig}; #[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct ChargeAssetTxPayment { From cc91900c9645d73d5b0de81f97007d4628980b57 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Mon, 10 Jul 2023 15:38:22 +0200 Subject: [PATCH 10/28] include port, use different names --- examples/parachain-example/Cargo.lock | 9 +++-- .../asset-hub-zombienet.toml | 3 +- .../parachain-example/src/bin/fetch_blocks.rs | 2 +- .../src/bin/submit_transaction.rs | 19 ++++------ examples/parachain-example/src/lib.rs | 38 +++++++++---------- 5 files changed, 34 insertions(+), 37 deletions(-) diff --git a/examples/parachain-example/Cargo.lock b/examples/parachain-example/Cargo.lock index 075412ba4a..a4ad155e55 100644 --- a/examples/parachain-example/Cargo.lock +++ b/examples/parachain-example/Cargo.lock @@ -1814,9 +1814,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -3033,11 +3033,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", diff --git a/examples/parachain-example/asset-hub-zombienet.toml b/examples/parachain-example/asset-hub-zombienet.toml index 89bfaf0570..ed97dc09cc 100644 --- a/examples/parachain-example/asset-hub-zombienet.toml +++ b/examples/parachain-example/asset-hub-zombienet.toml @@ -1,7 +1,7 @@ [relaychain] default_image = "docker.io/parity/polkadot:latest" default_command = "polkadot" -default_args = [ "-lparachain=debug" ] +default_args = ["-lparachain=debug"] chain = "rococo-local" @@ -20,6 +20,7 @@ chain = "asset-hub-polkadot-local" [parachains.collator] name = "collator01" image = "docker.io/parity/polkadot-parachain:latest" + ws_port = 42069 command = "polkadot-parachain" args = ["-lparachain=debug"] \ No newline at end of file diff --git a/examples/parachain-example/src/bin/fetch_blocks.rs b/examples/parachain-example/src/bin/fetch_blocks.rs index b32dedf8f3..4baf3459d7 100644 --- a/examples/parachain-example/src/bin/fetch_blocks.rs +++ b/examples/parachain-example/src/bin/fetch_blocks.rs @@ -1,5 +1,5 @@ //! In this example we connect to the official polkadot asset hub parachain and subscribe to blocks that get produced. -//! You can just switch out `StatemintConfig` for `StatemintConfig2` or `StatemintConfig3` and the behavior should be the same. +//! You can just switch out `StatemintConfig` for `StatemintConfigWithSubxtTypes` or `StatemintConfigComposed` and the behavior should be the same. //! //! To run this example: //! ```txt diff --git a/examples/parachain-example/src/bin/submit_transaction.rs b/examples/parachain-example/src/bin/submit_transaction.rs index 003d7c353d..70c73b3f28 100644 --- a/examples/parachain-example/src/bin/submit_transaction.rs +++ b/examples/parachain-example/src/bin/submit_transaction.rs @@ -51,23 +51,21 @@ //! Polkadot / Kusama / Rococo have different epoch times of `24h` / `2h` / `2min` respectively. //! The parachain is only registered after the first epoch. So we need to wait 2 minutes, until the parachain becomes interactive and produces blocks. //! -//! //! # Running the example //! -//! After you have the network running, you should see something like [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:41955#/explorer] -//! as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. Here `41955` refers to the port, -//! which we will need shortly. +//! After you have the network running, you should see something like [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:42069#/explorer] +//! as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. //! -//! In this example we use the _uniques_ pallet of the polakdot asset hub parachain. +//! In this example we use the _uniques_ pallet of the polkadot asset hub parachain. //! The dev account _alice_ creates an NFT collection, then mints an NFT that is part of the collection. //! Beware that this example can take up to a minute to run. Specify the port like so: //! ```txt -//! cargo run --bin submit_transaction +//! cargo run --bin submit_transaction //! ``` //! use metadata::statemint; -use parachain_example::StatemintConfig3; +use parachain_example::StatemintConfigComposed; use subxt::{ utils::{AccountId32, MultiAddress}, OnlineClient, @@ -75,7 +73,7 @@ use subxt::{ use subxt_signer::sr25519::dev::{self}; -/// cargo run --bin submit_transaction +/// cargo run --bin submit_transaction #[tokio::main] pub async fn main() { if let Err(err) = run().await { @@ -84,11 +82,8 @@ pub async fn main() { } async fn run() -> Result<(), Box> { - let port = std::env::args().nth(1).expect("port must be specified"); - // Connecting to the local parachain. You might need to replace the port in `"ws://127.0.0.1:36317"` - // with a different value, depending on what your zombienet cli outputs to you. let api = - OnlineClient::::from_url(format!("ws://127.0.0.1:{}", port)).await?; + OnlineClient::::from_url("ws://127.0.0.1:42069").await?; println!("Connection with parachain established."); let alice: MultiAddress = dev::alice().public_key().into(); let alice_pair_signer = dev::alice(); diff --git a/examples/parachain-example/src/lib.rs b/examples/parachain-example/src/lib.rs index 63f9469213..cd3e9969e5 100644 --- a/examples/parachain-example/src/lib.rs +++ b/examples/parachain-example/src/lib.rs @@ -157,7 +157,7 @@ //! - [subxt::config::substrate::DigestItem] and [subxt::config::substrate::Digest] instead of types from [sp_runtime::generic::digest] //! - [subxt::config::substrate::ConsensusEngineId] instead of [sp_runtime::ConsensusEngineId] //! -//! With these optimizations, our config can look like the `StatemintConfig2` below. +//! With these optimizations, our config can look like the `StatemintConfigWithSubxtTypes` below. //! //! ## 2.3. Use the Substrate default config as much as possible //! @@ -169,9 +169,9 @@ //! Statemint (Polkadot Asset Hub) seems to match the Polkadot config in almost all points, except for the `ExtrinsicParams`. //! Here the tips follow the same structure as for the default substrate node. //! We can now simply build the config for Statemint from the building blocks provided -//! by [subxt::SubstrateConfig] and [subxt::PolkadotConfig] as shown below in `StatemintConfig3`. +//! by [subxt::SubstrateConfig] and [subxt::PolkadotConfig] as shown below in `StatemintConfigComposed`. //! -//! All configs we constructed, `StatemintConfig`, `StatemintConfig2` and `StatemintConfig3` should behave in the same way. +//! All configs we constructed, `StatemintConfig`, `StatemintConfigWithSubxtTypes` and `StatemintConfigComposed` should behave in the same way. //! All three ways are valid for constructing a config. Choose one depending on your use case. //! //! # 3 Try the examples @@ -273,9 +273,9 @@ impl ExtrinsicParams<::Index, ; - type ExtrinsicParams = StatemintExtrinsicParams; + type ExtrinsicParams = StatemintExtrinsicParamsWithSubxtTypes; } #[derive(Encode, Debug, Clone)] -pub struct StatemintExtrinsicParams2 { - extra_params: StatemintExtraParams2, - additional_params: StatemintAdditionalParams2, +pub struct StatemintExtrinsicParamsWithSubxtTypes { + extra_params: StatemintExtraParamsWithSubxtTypes, + additional_params: StatemintAdditionalParamsWithSubxtTypes, } #[derive(Encode, Debug, Clone)] -pub struct StatemintExtraParams2 { +pub struct StatemintExtraParamsWithSubxtTypes { era: subxt::config::extrinsic_params::Era, nonce: u32, charge: subxt::config::substrate::AssetTip, } #[derive(Encode, Debug, Clone)] -pub struct StatemintAdditionalParams2 { +pub struct StatemintAdditionalParamsWithSubxtTypes { spec_version: u32, tx_version: u32, genesis_hash: subxt::utils::H256, mortality_hash: subxt::utils::H256, } -impl ExtrinsicParams<::Index, ::Hash> - for StatemintExtrinsicParams2 +impl ExtrinsicParams<::Index, ::Hash> + for StatemintExtrinsicParamsWithSubxtTypes { /// mortality hash, era, charge type OtherParams = ( @@ -320,15 +320,15 @@ impl ExtrinsicParams<::Index, ::Index, - genesis_hash: ::Hash, + nonce: ::Index, + genesis_hash: ::Hash, other_params: Self::OtherParams, ) -> Self { let (mortality_hash, era, charge) = other_params; - let extra_params = StatemintExtraParams2 { era, nonce, charge }; + let extra_params = StatemintExtraParamsWithSubxtTypes { era, nonce, charge }; - let additional_params = StatemintAdditionalParams2 { + let additional_params = StatemintAdditionalParamsWithSubxtTypes { spec_version, tx_version, genesis_hash, @@ -353,9 +353,9 @@ impl ExtrinsicParams<::Index, ::Index; type Hash = ::Hash; type AccountId = ::AccountId; From aedea799ebfe4617c2b5dc18d5cc0c41c53ea231 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Mon, 10 Jul 2023 18:00:34 +0200 Subject: [PATCH 11/28] link the example from the book --- examples/parachain-example/src/lib.rs | 21 +++++++++++---------- subxt/src/book/setup/client.rs | 10 +++++++--- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/examples/parachain-example/src/lib.rs b/examples/parachain-example/src/lib.rs index cd3e9969e5..756760f882 100644 --- a/examples/parachain-example/src/lib.rs +++ b/examples/parachain-example/src/lib.rs @@ -1,17 +1,17 @@ -//! # Connecting to a parachain with Subxt +//! # Tutorial: Subxt setup to interact with custom chains //! -//! In this example we connect to a parachain and subscribe to its blocks. -//! There are many parachains on Polkadot and Kusama. Connecting to a parachain (or any other substrate based blockchain) with subxt requires 2 steps: +//! There are many parachains on Polkadot and Kusama. Using Subxt to connect to a parachain +//! (or any other custom, substrate based chain) requires 2 steps: //! //! 1. Fetching the chains metadata to generate a static interface via the subxt codegen. //! 2. Creating a config struct that implements `subxt::Config` to give some type information //! that is currently not covered by the metadata. //! -//! We now show these steps in detail. As an example we use the -//! ["Statemint"](https://parachains.info/details/statemint) parachain, also known as "Asset Hub" that is currently (2023-06-26) +//! We now show these steps in detail for the ["Statemint"](https://parachains.info/details/statemint) parachain, +//! also known as "Asset Hub" that is currently (as of 2023-06-26) //! deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). //! -//! ## 1. Fetch the Metadata +//! # 1. Fetch the Metadata //! //! To fetch the metadata for the Statemint parachain, we need to have the URL of an RPC node. //! We can find the "Asset Hub" entry, by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/). @@ -174,9 +174,10 @@ //! All configs we constructed, `StatemintConfig`, `StatemintConfigWithSubxtTypes` and `StatemintConfigComposed` should behave in the same way. //! All three ways are valid for constructing a config. Choose one depending on your use case. //! -//! # 3 Try the examples -//! We have two examples of interacting with the parachain, that you can try. You find them in the bin directory of this crate. Please check them out. -//! +//! # 3. Try the examples +//! +//! We have two examples of interacting with the parachain, that you can try. +//! You find them in the bin directory of this crate. Please check them out. //! use codec::Encode; use subxt::config::ExtrinsicParams; @@ -363,6 +364,6 @@ impl Config for StatemintConfigComposed { type Signature = ::Signature; type Hasher = ::Hasher; type Header = ::Header; - // this is the only difference: + // this is the only difference to the PolkadotConfig: type ExtrinsicParams = ::ExtrinsicParams; } diff --git a/subxt/src/book/setup/client.rs b/subxt/src/book/setup/client.rs index 88086d6213..c5f00fb879 100644 --- a/subxt/src/book/setup/client.rs +++ b/subxt/src/book/setup/client.rs @@ -11,15 +11,19 @@ //! //! Both clients are generic over a [`crate::config::Config`] trait, which is the way that we give //! the client certain information about how to interact with a node that isn't otherwise available -//! or possible to include in the node metadata. Subxt ships out of the box with two default -//! implementations: +//! or possible to include in the node metadata. +//! The [`crate::config::Config`] trait mimics the `frame_system::Config` trait and +//! subxt ships out of the box with two default implementations: //! //! - [`crate::config::PolkadotConfig`] for talking to Polkadot nodes, and //! - [`crate::config::SubstrateConfig`] for talking to generic nodes built with Substrate. //! //! The latter will generally work in many cases, but will need modifying if the chain you'd like to //! connect to has altered any of the details mentioned in [the trait](`crate::config::Config`). -//! +//! +//! For a detailed breakdown of how to construct a config for a custom chain, please refer to [the parachain example](../../../../../../examples/parachain-example/target/doc/parachain_example/index.html). +//! Usually the [`PolkadotConfig`](crate::config::PolkadotConfig) and [`SubstrateConfig`](crate::config::PolkadotConfig) should be sufficient though. +//! //! In the case of the [`crate::OnlineClient`], we have a few options to instantiate it: //! //! - [`crate::OnlineClient::new()`] to connect to a node running locally. From 72c4d7b02549bd6bb1f6b4e1c4db0a80f68447de Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Mon, 10 Jul 2023 18:48:40 +0200 Subject: [PATCH 12/28] format book --- subxt/src/book/setup/client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subxt/src/book/setup/client.rs b/subxt/src/book/setup/client.rs index c5f00fb879..e7a315251d 100644 --- a/subxt/src/book/setup/client.rs +++ b/subxt/src/book/setup/client.rs @@ -11,7 +11,7 @@ //! //! Both clients are generic over a [`crate::config::Config`] trait, which is the way that we give //! the client certain information about how to interact with a node that isn't otherwise available -//! or possible to include in the node metadata. +//! or possible to include in the node metadata. //! The [`crate::config::Config`] trait mimics the `frame_system::Config` trait and //! subxt ships out of the box with two default implementations: //! @@ -20,10 +20,10 @@ //! //! The latter will generally work in many cases, but will need modifying if the chain you'd like to //! connect to has altered any of the details mentioned in [the trait](`crate::config::Config`). -//! +//! //! For a detailed breakdown of how to construct a config for a custom chain, please refer to [the parachain example](../../../../../../examples/parachain-example/target/doc/parachain_example/index.html). //! Usually the [`PolkadotConfig`](crate::config::PolkadotConfig) and [`SubstrateConfig`](crate::config::PolkadotConfig) should be sufficient though. -//! +//! //! In the case of the [`crate::OnlineClient`], we have a few options to instantiate it: //! //! - [`crate::OnlineClient::new()`] to connect to a node running locally. From 7b590457c35e46b714c957fca35d705aa6beedcc Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Tue, 11 Jul 2023 12:31:05 +0200 Subject: [PATCH 13/28] add config creation to book, simplify example structure --- examples/parachain-example/Cargo.lock | 88 +++-- examples/parachain-example/Cargo.toml | 4 +- .../create_nft.rs} | 7 +- .../{src/bin => examples}/fetch_blocks.rs | 5 +- .../parachain-example/metadata/Cargo.toml | 7 - .../parachain-example/metadata/src/lib.rs | 2 - examples/parachain-example/src/lib.rs | 366 ++---------------- .../src/statemint_config_composed.rs | 17 + .../src/statemint_config_verbose.rs | 88 +++++ .../src/statemint_config_with_subxt_types.rs | 79 ++++ .../{metadata => }/statemint_metadata.scale | Bin subxt/src/book/mod.rs | 3 +- subxt/src/book/setup/client.rs | 8 +- subxt/src/book/setup/config.rs | 156 ++++++++ subxt/src/book/setup/mod.rs | 1 + 15 files changed, 423 insertions(+), 408 deletions(-) rename examples/parachain-example/{src/bin/submit_transaction.rs => examples/create_nft.rs} (96%) rename examples/parachain-example/{src/bin => examples}/fetch_blocks.rs (92%) delete mode 100644 examples/parachain-example/metadata/Cargo.toml delete mode 100644 examples/parachain-example/metadata/src/lib.rs create mode 100644 examples/parachain-example/src/statemint_config_composed.rs create mode 100644 examples/parachain-example/src/statemint_config_verbose.rs create mode 100644 examples/parachain-example/src/statemint_config_with_subxt_types.rs rename examples/parachain-example/{metadata => }/statemint_metadata.scale (100%) create mode 100644 subxt/src/book/setup/config.rs diff --git a/examples/parachain-example/Cargo.lock b/examples/parachain-example/Cargo.lock index a4ad155e55..c023a33ca5 100644 --- a/examples/parachain-example/Cargo.lock +++ b/examples/parachain-example/Cargo.lock @@ -130,7 +130,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -534,7 +534,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -556,7 +556,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core 0.20.1", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -831,7 +831,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -1446,7 +1446,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -1506,13 +1506,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "metadata" -version = "0.1.0" -dependencies = [ - "subxt", -] - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1609,7 +1602,6 @@ name = "parachain-example" version = "0.1.0" dependencies = [ "futures", - "metadata", "parity-scale-codec", "scale-decode", "scale-encode", @@ -1696,9 +1688,9 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", ] @@ -1726,7 +1718,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -1924,18 +1916,19 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.3.2", + "regex-syntax 0.7.4", ] [[package]] @@ -1947,6 +1940,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1955,9 +1959,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "ring" @@ -2301,9 +2305,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.164" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" dependencies = [ "serde_derive", ] @@ -2319,20 +2323,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" dependencies = [ "itoa", "ryu", @@ -2550,7 +2554,7 @@ checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -2669,7 +2673,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -2888,7 +2892,7 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.22", + "syn 2.0.25", "thiserror", "tokio", ] @@ -2900,7 +2904,7 @@ dependencies = [ "darling 0.20.1", "proc-macro-error", "subxt-codegen", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -2922,7 +2926,7 @@ dependencies = [ "hex", "hmac 0.12.1", "parity-scale-codec", - "pbkdf2 0.12.1", + "pbkdf2 0.12.2", "regex", "schnorrkel 0.10.2", "secrecy", @@ -2946,9 +2950,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.22" +version = "2.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" dependencies = [ "proc-macro2", "quote", @@ -2984,7 +2988,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -3057,7 +3061,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -3129,7 +3133,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] [[package]] @@ -3341,7 +3345,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", "wasm-bindgen-shared", ] @@ -3363,7 +3367,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3764,5 +3768,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.25", ] diff --git a/examples/parachain-example/Cargo.toml b/examples/parachain-example/Cargo.toml index 0704b78e50..82675aee91 100644 --- a/examples/parachain-example/Cargo.toml +++ b/examples/parachain-example/Cargo.toml @@ -4,14 +4,12 @@ version = "0.1.0" edition = "2021" [workspace] -members = ["./metadata"] [dependencies] subxt = { path = "../../subxt" } -subxt-signer = { path = "../../signer", features=["subxt"] } +subxt-signer = { path = "../../signer", features = ["subxt"] } futures = { version = "0.3.27", default-features = false, features = ["std"] } tokio = { version = "1.28", features = ["macros", "time", "rt-multi-thread"] } -metadata = { path = "./metadata" } sp-core = "21.0.0" sp-runtime = "24.0.0" codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } diff --git a/examples/parachain-example/src/bin/submit_transaction.rs b/examples/parachain-example/examples/create_nft.rs similarity index 96% rename from examples/parachain-example/src/bin/submit_transaction.rs rename to examples/parachain-example/examples/create_nft.rs index 70c73b3f28..312fad2db4 100644 --- a/examples/parachain-example/src/bin/submit_transaction.rs +++ b/examples/parachain-example/examples/create_nft.rs @@ -64,8 +64,8 @@ //! ``` //! -use metadata::statemint; -use parachain_example::StatemintConfigComposed; +use parachain_example::statemint; +use parachain_example::statemint_config_composed::StatemintConfig; use subxt::{ utils::{AccountId32, MultiAddress}, OnlineClient, @@ -82,8 +82,7 @@ pub async fn main() { } async fn run() -> Result<(), Box> { - let api = - OnlineClient::::from_url("ws://127.0.0.1:42069").await?; + let api = OnlineClient::::from_url("ws://127.0.0.1:42069").await?; println!("Connection with parachain established."); let alice: MultiAddress = dev::alice().public_key().into(); let alice_pair_signer = dev::alice(); diff --git a/examples/parachain-example/src/bin/fetch_blocks.rs b/examples/parachain-example/examples/fetch_blocks.rs similarity index 92% rename from examples/parachain-example/src/bin/fetch_blocks.rs rename to examples/parachain-example/examples/fetch_blocks.rs index 4baf3459d7..bf4d6f417b 100644 --- a/examples/parachain-example/src/bin/fetch_blocks.rs +++ b/examples/parachain-example/examples/fetch_blocks.rs @@ -6,8 +6,9 @@ //! cargo run --bin fetch_blocks //! ``` +use parachain_example::statemint; use futures::StreamExt; -use parachain_example::StatemintConfig; +use parachain_example::statemint_config_composed::StatemintConfig; use subxt::OnlineClient; /// cargo run --bin fetch_blocks @@ -39,7 +40,7 @@ async fn main() -> Result<(), Box> { let events = ext.events().await?; // here we make use of the generated metadata code: - let decoded_ext = ext.as_root_extrinsic::(); + let decoded_ext = ext.as_root_extrinsic::(); println!(" Extrinsic #{idx}:"); println!(" Bytes: {}", ext.bytes().len()); diff --git a/examples/parachain-example/metadata/Cargo.toml b/examples/parachain-example/metadata/Cargo.toml deleted file mode 100644 index 9276a92afc..0000000000 --- a/examples/parachain-example/metadata/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "metadata" -version = "0.1.0" -edition = "2021" - -[dependencies] -subxt = { path = "../../../subxt" } \ No newline at end of file diff --git a/examples/parachain-example/metadata/src/lib.rs b/examples/parachain-example/metadata/src/lib.rs deleted file mode 100644 index 5bb31dae72..0000000000 --- a/examples/parachain-example/metadata/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] -pub mod statemint {} diff --git a/examples/parachain-example/src/lib.rs b/examples/parachain-example/src/lib.rs index 756760f882..b3380040ba 100644 --- a/examples/parachain-example/src/lib.rs +++ b/examples/parachain-example/src/lib.rs @@ -1,17 +1,29 @@ //! # Tutorial: Subxt setup to interact with custom chains //! -//! There are many parachains on Polkadot and Kusama. Using Subxt to connect to a parachain +//! There are many parachains on Polkadot and Kusama. Using Subxt to connect to a parachain //! (or any other custom, substrate based chain) requires 2 steps: //! //! 1. Fetching the chains metadata to generate a static interface via the subxt codegen. //! 2. Creating a config struct that implements `subxt::Config` to give some type information //! that is currently not covered by the metadata. //! -//! We now show these steps in detail for the ["Statemint"](https://parachains.info/details/statemint) parachain, -//! also known as "Asset Hub" that is currently (as of 2023-06-26) -//! deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). +//! This example shows you how to connect to the ["Statemint"](https://parachains.info/details/statemint) parachain, +//! also known as "Asset Hub", both locally and remotely. //! -//! # 1. Fetch the Metadata +//! ### Example 1: Subscribe to blocks of the official ["Polkadot Asset Hub"](https://parachains.info/details/statemint) +//! +//! ``` +//! cargo run --example fetch_blocks.rs +//! ``` +//! +//! ### Example 2: Create an NFT on a local parachain +//! +//! This requires you to spin up a local asset hub parachain using Zombienet. Please see the instructions in the example. +//! ``` +//! cargo run --example create_nft.rs +//! ``` +//! +//! # How to get the parachains metadata //! //! To fetch the metadata for the Statemint parachain, we need to have the URL of an RPC node. //! We can find the "Asset Hub" entry, by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/). @@ -19,351 +31,21 @@ //! In the URL of the page we can already see the URL of the RPC endpoint of the node as a query parameter. It is also printed //! to the Javascript console of the browser: `WS endpoint= wss://polkadot-asset-hub-rpc.polkadot.io`. //! -//! Let's create a separate crate for the statically generated interface. -//! Keeping the metadata and the resulting generated code in a separate crate -//! avoids unnecessary recompiles, whenever you change something in the rest of your project. -//! -//! ```txt -//! cargo new metadata --lib -//! ``` -//! -//! In the new crate we can now get the metadata via the [subxt cli](https://crates.io/crates/subxt-cli) tool. +//! We can now get the metadata via the [subxt cli](https://crates.io/crates/subxt-cli) tool. //! It is important to specify the port as `:443` like so: //! ```txt //! subxt metadata --url wss://polkadot-asset-hub-rpc.polkadot.io:443 > statemint_metadata.scale //! ``` -//! The metadata is saved as `statemint_metadata.scale`. We need to add subxt as a dependency with `cargo add subxt` -//! and then we can replace the code in lib.rs with the following: +//! The metadata is saved as `statemint_metadata.scale` and can be used to create the statically generated interface for the parachain: //! ``` //! #[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] //! pub mod statemint {} //! ``` -//! We use the `metadata` crate as a dependency in our main project and have access to -//! all the pallets and calls of Ajuna via the exported module `metadata::statemint`. -//! -//! # 2. Create the Config -//! -//! To construct a config, we need to investigate which types Statemint uses as `AccountId`, `Hasher`, etc. -//! We need to take a look at the source code of Statemint and find out how it implements some substrate functionalities. -//! Statemint (Polkadot Asset Hub) is part of the [Cumulus Github repository](https://github.com/paritytech/cumulus). -//! The crate defining the parachains runtime can be found [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot). -//! -//! ## 2.1 Create the config from scratch -//! -//! First we want to create the config from scratch to understand all the details. -//! -//! ### AccountId, Index, Hash, Hasher and Header -//! We need to check, where the parachains runtime implements the frame_system::Config trait. -//! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. -//! For Statemint we find it [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179). -//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::Config] should also be the ones -//! we want to use for implementing [subxt::Config]. -//! In the Case of Statemint (Asset Hub) they are: -//! -//! - AccountId: [sp_core::crypto::AccountId32] -//! - Index: [u32] -//! - Hash: [sp_core::H256] -//! - Hasher (type `Hashing` in [frame_system::Config]): [sp_runtime::traits::BlakeTwo256] -//! - Header: [sp_runtime::generic::Header](sp_runtime::generic::Header) -//! -//! ### Address, Signature, ExtrinsicParams -//! A Substrate runtime is typically constructed by using the [frame_support::construct_runtime] macro. -//! In this macro, we need to specify the type of an `UncheckedExtrinsic`. Most of the time, the `UncheckedExtrinsic` will be of the type -//! [sp_runtime::generic::UncheckedExtrinsic](sp_runtime::generic::UncheckedExtrinsic). -//! The generic parameters `Address` and `Signature` specified when declaring the `UncheckedExtrinsic` type -//! are the types for `Address` and `Signature` we should use when implementing the [subxt::Config] trait. -//! In case of Statemint (Polkadot Asset Hub) we see the following types being used in `UncheckedExtrinsic`: -//! -//! - Address: [sp_runtime::MultiAddress](sp_runtime::MultiAddress) -//! - Signature: [sp_runtime::MultiSignature] -//! -//! #### ExtrinsicParams -//! The `ExtrinsicParams` type is the most complicated to set up, but it can be derived from -//! the `SignedExtra` parameter of the `UncheckedExtrinsic` of your parachain. The `SignedExtra` parameter is a tuple in most cases, -//! where each field of the tuple corresponds to 0-1 fields in the `ExtrinsicParams` struct we want to create. -//! It looks like [this](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L779) for the Statemint parachain: -//! -//! ```rs -//! pub type SignedExtra = ( -//! frame_system::CheckNonZeroSender, -//! frame_system::CheckSpecVersion, -//! frame_system::CheckTxVersion, -//! frame_system::CheckGenesis, -//! frame_system::CheckEra, -//! frame_system::CheckNonce, -//! frame_system::CheckWeight, -//! pallet_asset_tx_payment::ChargeAssetTxPayment, -//! ); -//! ``` -//! -//! The `ExtrinsicParams` struct is basically a collection of fields that can be grouped into two categories: -//! _extra parameters_ and _additional parameters_. _Extra parameters_ are taken into account when -//! signing a transaction and sent along with it, while _additional parameters_ are only used during -//! the signing step but _not_ sent along with the transaction. -//! -//! Each element of the `SignedExtra` tuple implements [parity_scale_codec::codec::Encode] and [sp_runtime::traits::SignedExtension] -//! which has an associated type `AdditionalSigned` that also implements [parity_scale_codec::codec::Encode]. Let's look at the underlying types for each tuple element. -//! All zero-sized types have been replaced by `()` for simplicity. -//! -//! | tuple element | struct type | `AdditionalSigned` type | -//! | ------------------------------------ | ----------------------------------------------- | ---------------------------------| -//! | [frame_system::CheckNonZeroSender] | () | () | -//! | [frame_system::CheckSpecVersion] | () | [u32] | -//! | [frame_system::CheckTxVersion] | () | [u32] | -//! | [frame_system::CheckGenesis] | () | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckMortality] | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckNonce] | [Config::Index] = [u32] | () | -//! | [frame_system::CheckWeight] | () | () | -//! | [frame_system::ChargeAssetTxPayment] | [pallet_asset_tx_payment::ChargeAssetTxPayment] | () | -//! -//! All types in the `struct type` column make up our _extra parameters_. -//! We can put them together into a struct, ignoring all zero-sized types. -//! The types of the last column make up our _additional parameters_. Here -//! we can also ignore the zero-sized types. We can name the fields however we like, -//! however their order in the struct should match the order in the `SignedExtra` tuple (see table). -//! Beware that some numbers might be compact encoded, when encoding the struct, some might not be. -//! Please check the exact struct type definition here. For example the definition for CheckNonce is -//! `CheckNonce(#[codec(compact)] pub T::Index)`. We can see that the `#[codec(compact)` -//! attribute tells us that the `u32` value needs to be compact encoded. -//! -//! Because the `pallet_asset_tx_payment::ChargeAssetTxPayment` struct requires us to pass the -//! struct of our `Runtime` as a generic argument, we decide to just recreate the struct here. This prohibits us -//! from pulling in tons of unneeded dependencies. This is a pattern that you might see often, -//! especially because substrate crates and their types are quite big, clunky and entangled sometimes. -//! -//! With all these types collected, we can create two structs: `StatemintExtraParams` and `StatemintAdditionalParams`. -//! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [subxt::config::ExtrinsicParams] trait, see below. -//! Now we have all the parts we need to create our config `StatemintConfig` and implment the [subxt::Config] trait on it. -//! Note that StatemintConfig is an empty enum, an _uninhabited type_ that is never means to be instantiated -//! but just gives type information to various interfaces of _subxt_. -//! -//! ## 2.2 Simplifying the config -//! -//! Now you should be able to create a config for a parachain from scratch and understand the details of its construction. -//! However this is quite a tedious process, so subxt provides some sane defaults that can make your life easier. -//! First, let's ditch the dependencies to [sp_core] and [sp_runtime]. -//! We should not be forced to utilize these traits whenever we create a config for a chain. -//! That is why subxt provides some types that can function as drop in replacements for some types in [sp_core] and [sp_runtime]. -//! You can use: -//! - [subxt::config::extrinsic_params::Era] instead of [sp_runtime::generic::Era] -//! - [subxt::utils::AccountId32] instead of [sp_core::crypto::AccountId32] -//! - [subxt::utils::MultiAddress] instead of [sp_runtime::MultiAddress] -//! - [subxt::utils::H160], [subxt::utils::H256] and [subxt::utils::H512] instead of [sp_core::H256], [sp_core::H160] and [sp_core::H512] -//! - [subxt::hash] instead of [sp_runtime::MultiAddress] -//! - [subxt::config::substrate::Era] instead of [sp_runtime::generic::Era] -//! - [subxt::config::substrate::SubstrateHeader] instead of [sp_runtime::generic::Header] -//! - [subxt::config::substrate::AssetTip] and [subxt::config::polkadot::PlainTip] instead of [pallet_transaction_payment::ChargeTransactionPayment] -//! - [subxt::config::substrate::BlakeTwo256] instead of [sp_core::Blake2Hasher] or [sp_runtime::traits::BlakeTwo256] -//! - [subxt::config::substrate::DigestItem] and [subxt::config::substrate::Digest] instead of types from [sp_runtime::generic::digest] -//! - [subxt::config::substrate::ConsensusEngineId] instead of [sp_runtime::ConsensusEngineId] -//! -//! With these optimizations, our config can look like the `StatemintConfigWithSubxtTypes` below. //! -//! ## 2.3. Use the Substrate default config as much as possible -//! -//! Because most substrate based chains share a great deal of types, _subxt_ already provides two configs: -//! - [subxt::SubstrateConfig] configured for the default [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) -//! - [subxt::PolkadotConfig] configured for the [polkadot node implementation](https://github.com/paritytech/polkadot) -//! -//! Even those two just differ in the type of the `Tip` and `MultiAddress`. -//! Statemint (Polkadot Asset Hub) seems to match the Polkadot config in almost all points, except for the `ExtrinsicParams`. -//! Here the tips follow the same structure as for the default substrate node. -//! We can now simply build the config for Statemint from the building blocks provided -//! by [subxt::SubstrateConfig] and [subxt::PolkadotConfig] as shown below in `StatemintConfigComposed`. -//! -//! All configs we constructed, `StatemintConfig`, `StatemintConfigWithSubxtTypes` and `StatemintConfigComposed` should behave in the same way. -//! All three ways are valid for constructing a config. Choose one depending on your use case. -//! -//! # 3. Try the examples -//! -//! We have two examples of interacting with the parachain, that you can try. -//! You find them in the bin directory of this crate. Please check them out. -//! -use codec::Encode; -use subxt::config::ExtrinsicParams; -use subxt::{Config, PolkadotConfig, SubstrateConfig}; - -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct ChargeAssetTxPayment { - #[codec(compact)] - tip: u128, - asset_id: Option, -} - -//////////////////////////////////////////////////////////// -// First Config (verbose and detailed) -//////////////////////////////////////////////////////////// - -pub enum StatemintConfig {} - -impl Config for StatemintConfig { - type Index = u32; - type Hash = sp_core::H256; - type AccountId = sp_core::crypto::AccountId32; - type Address = sp_runtime::MultiAddress; - type Signature = sp_runtime::MultiSignature; - type Hasher = sp_runtime::traits::BlakeTwo256; - type Header = sp_runtime::generic::Header; - type ExtrinsicParams = StatemintExtrinsicParams; -} - -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct StatemintExtrinsicParams { - extra_params: StatemintExtraParams, - additional_params: StatemintAdditionalParams, -} - -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct StatemintExtraParams { - era: sp_runtime::generic::Era, - nonce: u32, - charge: ChargeAssetTxPayment, -} - -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct StatemintAdditionalParams { - spec_version: u32, - tx_version: u32, - genesis_hash: sp_core::H256, - mortality_hash: sp_core::H256, -} - -impl ExtrinsicParams<::Index, ::Hash> - for StatemintExtrinsicParams -{ - /// mortality hash, era, charge - type OtherParams = ( - sp_core::H256, - sp_runtime::generic::Era, - ChargeAssetTxPayment, - ); - - fn new( - spec_version: u32, - tx_version: u32, - nonce: ::Index, - genesis_hash: ::Hash, - other_params: Self::OtherParams, - ) -> Self { - let (mortality_hash, era, charge) = other_params; - - let extra_params = StatemintExtraParams { era, nonce, charge }; - - let additional_params = StatemintAdditionalParams { - spec_version, - tx_version, - genesis_hash, - mortality_hash, - }; - Self { - extra_params, - additional_params, - } - } - - fn encode_extra_to(&self, v: &mut Vec) { - self.extra_params.encode_to(v); - } - - fn encode_additional_to(&self, v: &mut Vec) { - self.additional_params.encode_to(v); - } -} - -//////////////////////////////////////////////////////////// -// Second Config (just using subxt types) -//////////////////////////////////////////////////////////// - -pub enum StatemintConfigWithSubxtTypes {} - -impl Config for StatemintConfigWithSubxtTypes { - type Index = u32; - type Hash = subxt::utils::H256; - type AccountId = subxt::utils::AccountId32; - type Address = subxt::utils::MultiAddress; - type Signature = subxt::utils::MultiSignature; - type Hasher = subxt::config::substrate::BlakeTwo256; - type Header = subxt::config::substrate::SubstrateHeader; - type ExtrinsicParams = StatemintExtrinsicParamsWithSubxtTypes; -} - -#[derive(Encode, Debug, Clone)] -pub struct StatemintExtrinsicParamsWithSubxtTypes { - extra_params: StatemintExtraParamsWithSubxtTypes, - additional_params: StatemintAdditionalParamsWithSubxtTypes, -} - -#[derive(Encode, Debug, Clone)] -pub struct StatemintExtraParamsWithSubxtTypes { - era: subxt::config::extrinsic_params::Era, - nonce: u32, - charge: subxt::config::substrate::AssetTip, -} - -#[derive(Encode, Debug, Clone)] -pub struct StatemintAdditionalParamsWithSubxtTypes { - spec_version: u32, - tx_version: u32, - genesis_hash: subxt::utils::H256, - mortality_hash: subxt::utils::H256, -} - -impl ExtrinsicParams<::Index, ::Hash> - for StatemintExtrinsicParamsWithSubxtTypes -{ - /// mortality hash, era, charge - type OtherParams = ( - subxt::utils::H256, - subxt::config::extrinsic_params::Era, - subxt::config::substrate::AssetTip, - ); - - fn new( - spec_version: u32, - tx_version: u32, - nonce: ::Index, - genesis_hash: ::Hash, - other_params: Self::OtherParams, - ) -> Self { - let (mortality_hash, era, charge) = other_params; - - let extra_params = StatemintExtraParamsWithSubxtTypes { era, nonce, charge }; - - let additional_params = StatemintAdditionalParamsWithSubxtTypes { - spec_version, - tx_version, - genesis_hash, - mortality_hash, - }; - Self { - extra_params, - additional_params, - } - } - - fn encode_extra_to(&self, v: &mut Vec) { - self.extra_params.encode_to(v); - } - - fn encode_additional_to(&self, v: &mut Vec) { - self.additional_params.encode_to(v); - } -} - -//////////////////////////////////////////////////////////// -// Third Config (using the Substrate and Polkadot Config) -//////////////////////////////////////////////////////////// -pub enum StatemintConfigComposed {} +pub mod statemint_config_composed; +pub mod statemint_config_verbose; +pub mod statemint_config_with_subxt_types; -impl Config for StatemintConfigComposed { - type Index = ::Index; - type Hash = ::Hash; - type AccountId = ::AccountId; - type Address = ::Address; - type Signature = ::Signature; - type Hasher = ::Hasher; - type Header = ::Header; - // this is the only difference to the PolkadotConfig: - type ExtrinsicParams = ::ExtrinsicParams; -} +#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] +pub mod statemint {} diff --git a/examples/parachain-example/src/statemint_config_composed.rs b/examples/parachain-example/src/statemint_config_composed.rs new file mode 100644 index 0000000000..8538abfbcf --- /dev/null +++ b/examples/parachain-example/src/statemint_config_composed.rs @@ -0,0 +1,17 @@ +use codec::Encode; +use subxt::config::ExtrinsicParams; +use subxt::{Config, PolkadotConfig, SubstrateConfig}; + +pub enum StatemintConfig {} + +impl Config for StatemintConfig { + type Index = ::Index; + type Hash = ::Hash; + type AccountId = ::AccountId; + type Address = ::Address; + type Signature = ::Signature; + type Hasher = ::Hasher; + type Header = ::Header; + // this is the only difference to the PolkadotConfig: + type ExtrinsicParams = ::ExtrinsicParams; +} diff --git a/examples/parachain-example/src/statemint_config_verbose.rs b/examples/parachain-example/src/statemint_config_verbose.rs new file mode 100644 index 0000000000..0be7d07056 --- /dev/null +++ b/examples/parachain-example/src/statemint_config_verbose.rs @@ -0,0 +1,88 @@ +use codec::Encode; +use subxt::config::ExtrinsicParams; +use subxt::{Config, PolkadotConfig, SubstrateConfig}; + +pub enum StatemintConfig {} + +impl Config for StatemintConfig { + type Index = u32; + type Hash = sp_core::H256; + type AccountId = sp_core::crypto::AccountId32; + type Address = sp_runtime::MultiAddress; + type Signature = sp_runtime::MultiSignature; + type Hasher = sp_runtime::traits::BlakeTwo256; + type Header = sp_runtime::generic::Header; + type ExtrinsicParams = StatemintExtrinsicParams; +} + +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintExtrinsicParams { + extra_params: StatemintExtraParams, + additional_params: StatemintAdditionalParams, +} + +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintExtraParams { + era: sp_runtime::generic::Era, + nonce: u32, + charge: ChargeAssetTxPayment, +} + +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct ChargeAssetTxPayment { + #[codec(compact)] + tip: u128, + asset_id: Option, +} + +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintAdditionalParams { + spec_version: u32, + tx_version: u32, + genesis_hash: sp_core::H256, + mortality_hash: sp_core::H256, +} + +impl ExtrinsicParams<::Index, ::Hash> +for StatemintExtrinsicParams +{ + /// mortality hash, era, charge + type OtherParams = ( + sp_core::H256, + sp_runtime::generic::Era, + ChargeAssetTxPayment, + ); + + fn new( + spec_version: u32, + tx_version: u32, + nonce: ::Index, + genesis_hash: ::Hash, + other_params: Self::OtherParams, + ) -> Self { + let (mortality_hash, era, charge) = other_params; + + let extra_params = StatemintExtraParams { era, nonce, charge }; + + let additional_params = StatemintAdditionalParams { + spec_version, + tx_version, + genesis_hash, + mortality_hash, + }; + Self { + extra_params, + additional_params, + } + } + + fn encode_extra_to(&self, v: &mut Vec) { + self.extra_params.encode_to(v); + } + + fn encode_additional_to(&self, v: &mut Vec) { + self.additional_params.encode_to(v); + } +} + + diff --git a/examples/parachain-example/src/statemint_config_with_subxt_types.rs b/examples/parachain-example/src/statemint_config_with_subxt_types.rs new file mode 100644 index 0000000000..9883195ba4 --- /dev/null +++ b/examples/parachain-example/src/statemint_config_with_subxt_types.rs @@ -0,0 +1,79 @@ +use codec::Encode; +use subxt::config::ExtrinsicParams; +use subxt::{Config, PolkadotConfig, SubstrateConfig}; + +pub enum StatemintConfig {} + +impl Config for StatemintConfig { + type Index = u32; + type Hash = subxt::utils::H256; + type AccountId = subxt::utils::AccountId32; + type Address = subxt::utils::MultiAddress; + type Signature = subxt::utils::MultiSignature; + type Hasher = subxt::config::substrate::BlakeTwo256; + type Header = subxt::config::substrate::SubstrateHeader; + type ExtrinsicParams = StatemintExtrinsicParams; +} + +#[derive(Encode, Debug, Clone)] +pub struct StatemintExtrinsicParams { + extra_params: StatemintExtraParams, + additional_params: StatemintAdditionalParams, +} + +#[derive(Encode, Debug, Clone)] +pub struct StatemintExtraParams { + era: subxt::config::extrinsic_params::Era, + nonce: u32, + charge: subxt::config::substrate::AssetTip, +} + +#[derive(Encode, Debug, Clone)] +pub struct StatemintAdditionalParams { + spec_version: u32, + tx_version: u32, + genesis_hash: subxt::utils::H256, + mortality_hash: subxt::utils::H256, +} + +impl ExtrinsicParams<::Index, ::Hash> +for StatemintExtrinsicParams +{ + /// mortality hash, era, charge + type OtherParams = ( + subxt::utils::H256, + subxt::config::extrinsic_params::Era, + subxt::config::substrate::AssetTip, + ); + + fn new( + spec_version: u32, + tx_version: u32, + nonce: ::Index, + genesis_hash: ::Hash, + other_params: Self::OtherParams, + ) -> Self { + let (mortality_hash, era, charge) = other_params; + + let extra_params = StatemintExtraParams { era, nonce, charge }; + + let additional_params = StatemintAdditionalParams { + spec_version, + tx_version, + genesis_hash, + mortality_hash, + }; + Self { + extra_params, + additional_params, + } + } + + fn encode_extra_to(&self, v: &mut Vec) { + self.extra_params.encode_to(v); + } + + fn encode_additional_to(&self, v: &mut Vec) { + self.additional_params.encode_to(v); + } +} diff --git a/examples/parachain-example/metadata/statemint_metadata.scale b/examples/parachain-example/statemint_metadata.scale similarity index 100% rename from examples/parachain-example/metadata/statemint_metadata.scale rename to examples/parachain-example/statemint_metadata.scale diff --git a/subxt/src/book/mod.rs b/subxt/src/book/mod.rs index 0123d3a685..8ac867a614 100644 --- a/subxt/src/book/mod.rs +++ b/subxt/src/book/mod.rs @@ -72,7 +72,8 @@ //! parachain node), you'll want to: //! //! 1. [Generate an interface](setup::codegen). -//! 2. [Configure and instantiate the client](setup::client). +//! 2. [Create a Config](setup::config). +//! 2. [Use the config to instantiate the client](setup::client). //! //! Follow the above links to learn more about each step. //! diff --git a/subxt/src/book/setup/client.rs b/subxt/src/book/setup/client.rs index e7a315251d..9329d7839a 100644 --- a/subxt/src/book/setup/client.rs +++ b/subxt/src/book/setup/client.rs @@ -12,17 +12,15 @@ //! Both clients are generic over a [`crate::config::Config`] trait, which is the way that we give //! the client certain information about how to interact with a node that isn't otherwise available //! or possible to include in the node metadata. +//! //! The [`crate::config::Config`] trait mimics the `frame_system::Config` trait and //! subxt ships out of the box with two default implementations: //! //! - [`crate::config::PolkadotConfig`] for talking to Polkadot nodes, and //! - [`crate::config::SubstrateConfig`] for talking to generic nodes built with Substrate. //! -//! The latter will generally work in many cases, but will need modifying if the chain you'd like to -//! connect to has altered any of the details mentioned in [the trait](`crate::config::Config`). -//! -//! For a detailed breakdown of how to construct a config for a custom chain, please refer to [the parachain example](../../../../../../examples/parachain-example/target/doc/parachain_example/index.html). -//! Usually the [`PolkadotConfig`](crate::config::PolkadotConfig) and [`SubstrateConfig`](crate::config::PolkadotConfig) should be sufficient though. +//! The latter will generally work in many cases, but [may need special customization](super::config) if +//! the node differs in any of the types the [`Config`](crate::config::Config) trait wants to know about. //! //! In the case of the [`crate::OnlineClient`], we have a few options to instantiate it: //! diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs new file mode 100644 index 0000000000..938427f4d6 --- /dev/null +++ b/subxt/src/book/setup/config.rs @@ -0,0 +1,156 @@ +//! # Creating a Config +//! +//! Subxt requires you to provide a type implementing [`crate::config::Config`] in order to connect to a node. +//! The [`crate::config::Config`] trait for the most part mimics the `frame_system::Config` trait. +//! For most use cases, you can just use one of the following Configs shipped with Subxt: +//! +//! - [`PolkadotConfig`](crate::config::PolkadotConfig) for talking to Polkadot nodes, and +//! - [`SubstrateConfig`](crate::config::SubstrateConfig) for talking to generic nodes built with Substrate. +//! +//! # How to create a Config for a custom chain? +//! +//! We now show in depth how a subxt Config can be created for a parachain, using the ["Statemint"](https://parachains.info/details/statemint) parachain, +//! also known as "Asset Hub" as an example. It is currently (as of 2023-06-26) +//! deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). +//! We also provide a separate example on [how to interact with the parachain](https://github.com/paritytech/subxt/tree/master/examples/parachain-example). +//! +//! To construct a config, we need to investigate which types Statemint uses as `AccountId`, `Hasher`, etc. +//! We need to take a look at the source code of Statemint and find out how it implements some substrate functionalities. +//! Statemint (Polkadot Asset Hub) is part of the [Cumulus Github repository](https://github.com/paritytech/cumulus). +//! The crate defining the parachains runtime can be found [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot). +//! +//! ## 1. Create the config from scratch +//! +//! First we want to create the config from scratch to understand all the details. +//! +//! ### AccountId, Index, Hash, Hasher and Header +//! We need to check, where the parachains runtime implements the frame_system::Config trait. +//! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. +//! For Statemint we find it [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179). +//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::Config] should also be the ones +//! we want to use for implementing [subxt::Config]. +//! In the Case of Statemint (Asset Hub) they are: +//! +//! - AccountId: [sp_core::crypto::AccountId32] +//! - Index: [u32] +//! - Hash: [sp_core::H256] +//! - Hasher (type `Hashing` in [frame_system::Config]): [sp_runtime::traits::BlakeTwo256] +//! - Header: [sp_runtime::generic::Header](sp_runtime::generic::Header) +//! +//! ### Address, Signature, ExtrinsicParams +//! A Substrate runtime is typically constructed by using the [frame_support::construct_runtime] macro. +//! In this macro, we need to specify the type of an `UncheckedExtrinsic`. Most of the time, the `UncheckedExtrinsic` will be of the type +//! [sp_runtime::generic::UncheckedExtrinsic](sp_runtime::generic::UncheckedExtrinsic). +//! The generic parameters `Address` and `Signature` specified when declaring the `UncheckedExtrinsic` type +//! are the types for `Address` and `Signature` we should use when implementing the [subxt::Config] trait. +//! In case of Statemint (Polkadot Asset Hub) we see the following types being used in `UncheckedExtrinsic`: +//! +//! - Address: [sp_runtime::MultiAddress](sp_runtime::MultiAddress) +//! - Signature: [sp_runtime::MultiSignature] +//! +//! #### ExtrinsicParams +//! The `ExtrinsicParams` type is the most complicated to set up, but it can be derived from +//! the `SignedExtra` parameter of the `UncheckedExtrinsic` of your parachain. The `SignedExtra` parameter is a tuple in most cases, +//! where each field of the tuple corresponds to 0-1 fields in the `ExtrinsicParams` struct we want to create. +//! It looks like [this](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L779) for the Statemint parachain: +//! +//! ```rs +//! pub type SignedExtra = ( +//! frame_system::CheckNonZeroSender, +//! frame_system::CheckSpecVersion, +//! frame_system::CheckTxVersion, +//! frame_system::CheckGenesis, +//! frame_system::CheckEra, +//! frame_system::CheckNonce, +//! frame_system::CheckWeight, +//! pallet_asset_tx_payment::ChargeAssetTxPayment, +//! ); +//! ``` +//! +//! The `ExtrinsicParams` struct is basically a collection of fields that can be grouped into two categories: +//! _extra parameters_ and _additional parameters_. _Extra parameters_ are taken into account when +//! signing a transaction and sent along with it, while _additional parameters_ are only used during +//! the signing step but _not_ sent along with the transaction. +//! +//! Each element of the `SignedExtra` tuple implements [parity_scale_codec::codec::Encode] and [sp_runtime::traits::SignedExtension] +//! which has an associated type `AdditionalSigned` that also implements [parity_scale_codec::codec::Encode]. Let's look at the underlying types for each tuple element. +//! All zero-sized types have been replaced by `()` for simplicity. +//! +//! | tuple element | struct type | `AdditionalSigned` type | +//! | ------------------------------------ | ----------------------------------------------- | ---------------------------------| +//! | [frame_system::CheckNonZeroSender] | () | () | +//! | [frame_system::CheckSpecVersion] | () | [u32] | +//! | [frame_system::CheckTxVersion] | () | [u32] | +//! | [frame_system::CheckGenesis] | () | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckMortality] | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckNonce] | [Config::Index] = [u32] | () | +//! | [frame_system::CheckWeight] | () | () | +//! | [frame_system::ChargeAssetTxPayment] | [pallet_asset_tx_payment::ChargeAssetTxPayment] | () | +//! +//! All types in the `struct type` column make up our _extra parameters_. +//! We can put them together into a struct, ignoring all zero-sized types. +//! The types of the last column make up our _additional parameters_. Here +//! we can also ignore the zero-sized types. We can name the fields however we like, +//! however their order in the struct should match the order in the `SignedExtra` tuple (see table). +//! Beware that some numbers might be compact encoded, when encoding the struct, some might not be. +//! Please check the exact struct type definition here. For example the definition for CheckNonce is +//! `CheckNonce(#[codec(compact)] pub T::Index)`. We can see that the `#[codec(compact)` +//! attribute tells us that the `u32` value needs to be compact encoded. +//! +//! Because the `pallet_asset_tx_payment::ChargeAssetTxPayment` struct requires us to pass the +//! struct of our `Runtime` as a generic argument, we decide to just recreate the struct here. This prohibits us +//! from pulling in tons of unneeded dependencies. This is a pattern that you might see often, +//! especially because substrate crates and their types are quite big, clunky and entangled sometimes. +//! +//! With all these types collected, we can create two structs: `StatemintExtraParams` and `StatemintAdditionalParams`. +//! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [subxt::config::ExtrinsicParams] trait, see below. +//! Now we have all the parts we need to create our config `StatemintConfig` and implment the [subxt::Config] trait on it. +//! Note that StatemintConfig is an empty enum, an _uninhabited type_ that is never means to be instantiated +//! but just gives type information to various interfaces of _subxt_. +//! +//! ```rust,ignore +#![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_verbose.rs")] +//! ``` +//! +//! ## 2. Simplifying the config +//! +//! Now you should be able to create a config for a parachain from scratch and understand the details of its construction. +//! However this is quite a tedious process, so subxt provides some sane defaults that can make your life easier. +//! First, let's ditch the dependencies to [sp_core] and [sp_runtime]. +//! We should not be forced to utilize these traits whenever we create a config for a chain. +//! That is why subxt provides some types that can function as drop in replacements for some types in [sp_core] and [sp_runtime]. +//! You can use: +//! - [crate::config::extrinsic_params::Era] instead of [sp_runtime::generic::Era] +//! - [crate::utils::AccountId32] instead of [sp_core::crypto::AccountId32] +//! - [crate::utils::MultiAddress] instead of [sp_runtime::MultiAddress] +//! - [crate::utils::H160], [crate::utils::H256] and [crate::utils::H512] instead of [sp_core::H256], [sp_core::H160] and [sp_core::H512] +//! - [crate::utils::MultiAddress] instead of [sp_runtime::MultiAddress] +//! - [crate::config::substrate::Era] instead of [sp_runtime::generic::Era] +//! - [crate::config::substrate::SubstrateHeader] instead of [sp_runtime::generic::Header] +//! - [crate::config::substrate::AssetTip] and [crate::config::polkadot::PlainTip] instead of [pallet_transaction_payment::ChargeTransactionPayment](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/struct.ChargeTransactionPayment.html) +//! - [crate::config::substrate::BlakeTwo256] instead of [sp_core::Blake2Hasher] or [sp_runtime::traits::BlakeTwo256] +//! - [crate::config::substrate::DigestItem] and [crate::config::substrate::Digest] instead of types from [sp_runtime::generic::digest] +//! - [crate::config::substrate::ConsensusEngineId] instead of [sp_runtime::ConsensusEngineId] +//! +//! With these optimizations, our config can look like this: +//! +//! ```rust,ignore +#![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_with_subxt_types.rs")] +//! ``` +//! +//! ## 3. Use the [`PolkadotConfig`](crate::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig) to compose a Config +//! +//! Because most substrate based chains share a great deal of types, _subxt_ already provides two configs: +//! - [`SubstrateConfig`](crate::SubstrateConfig) configured for the default [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) +//! - [`PolkadotConfig`](crate::PolkadotConfig) configured for the [polkadot node implementation](https://github.com/paritytech/polkadot) +//! +//! Even those two just differ in the type of the `Tip` and `MultiAddress`. +//! Statemint (Polkadot Asset Hub) seems to match the Polkadot config in almost all points, except for the `ExtrinsicParams`. +//! Here the tips follow the same structure as for the default substrate node. +//! We can now simply build the config for Statemint from the building blocks provided +//! by [subxt::SubstrateConfig] and [subxt::PolkadotConfig] as shown below. +//! +//! +//! ```rust,ignore +#![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_composed.rs")] +//! ``` \ No newline at end of file diff --git a/subxt/src/book/setup/mod.rs b/subxt/src/book/setup/mod.rs index f3f3c8e109..d491a2e160 100644 --- a/subxt/src/book/setup/mod.rs +++ b/subxt/src/book/setup/mod.rs @@ -11,3 +11,4 @@ pub mod client; pub mod codegen; +pub mod config; \ No newline at end of file From 874a55ce1d5d39e73e3bdfd5af77134a72207217 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Tue, 11 Jul 2023 13:22:22 +0200 Subject: [PATCH 14/28] fix the nft creation script --- examples/parachain-example/examples/create_nft.rs | 7 ++++--- .../parachain-example/src/statemint_config_composed.rs | 4 ++-- examples/parachain-example/src/statemint_config_verbose.rs | 2 +- .../src/statemint_config_with_subxt_types.rs | 2 +- subxt/src/book/mod.rs | 6 +++--- subxt/src/book/setup/config.rs | 2 +- subxt/src/book/setup/mod.rs | 2 +- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/parachain-example/examples/create_nft.rs b/examples/parachain-example/examples/create_nft.rs index 312fad2db4..84857fdb7c 100644 --- a/examples/parachain-example/examples/create_nft.rs +++ b/examples/parachain-example/examples/create_nft.rs @@ -46,14 +46,14 @@ //! ``` //! Zombienet uses Kubernetes by default, but we can use it without Kubernetes, by providing the `-p native` flag. //! -//! You might have notices, that we use `chain = "rococo-local"` in the `asset-hub-zombienet.toml` file for the relay chain. +//! You might have noticed, that we use `chain = "rococo-local"` in the `asset-hub-zombienet.toml` file for the relay chain. //! This is just to make the epoch time shorter and should have no effect on your interactions with the parachain. //! Polkadot / Kusama / Rococo have different epoch times of `24h` / `2h` / `2min` respectively. //! The parachain is only registered after the first epoch. So we need to wait 2 minutes, until the parachain becomes interactive and produces blocks. //! //! # Running the example //! -//! After you have the network running, you should see something like [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:42069#/explorer] +//! After you have the network up and running, you should see something like [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:42069#/explorer] //! as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. //! //! In this example we use the _uniques_ pallet of the polkadot asset hub parachain. @@ -82,7 +82,8 @@ pub async fn main() { } async fn run() -> Result<(), Box> { - let api = OnlineClient::::from_url("ws://127.0.0.1:42069").await?; + // (the port 42069 is specified in the asset-hub-zombienet.toml) + let api = OnlineClient::::from_url("ws://127.0.0.1:42069").await?; println!("Connection with parachain established."); let alice: MultiAddress = dev::alice().public_key().into(); let alice_pair_signer = dev::alice(); diff --git a/examples/parachain-example/src/statemint_config_composed.rs b/examples/parachain-example/src/statemint_config_composed.rs index 8538abfbcf..f18fbc630e 100644 --- a/examples/parachain-example/src/statemint_config_composed.rs +++ b/examples/parachain-example/src/statemint_config_composed.rs @@ -1,5 +1,5 @@ -use codec::Encode; -use subxt::config::ExtrinsicParams; + + use subxt::{Config, PolkadotConfig, SubstrateConfig}; pub enum StatemintConfig {} diff --git a/examples/parachain-example/src/statemint_config_verbose.rs b/examples/parachain-example/src/statemint_config_verbose.rs index 0be7d07056..5c4312bfe9 100644 --- a/examples/parachain-example/src/statemint_config_verbose.rs +++ b/examples/parachain-example/src/statemint_config_verbose.rs @@ -1,6 +1,6 @@ use codec::Encode; use subxt::config::ExtrinsicParams; -use subxt::{Config, PolkadotConfig, SubstrateConfig}; +use subxt::{Config}; pub enum StatemintConfig {} diff --git a/examples/parachain-example/src/statemint_config_with_subxt_types.rs b/examples/parachain-example/src/statemint_config_with_subxt_types.rs index 9883195ba4..8706e7b2c3 100644 --- a/examples/parachain-example/src/statemint_config_with_subxt_types.rs +++ b/examples/parachain-example/src/statemint_config_with_subxt_types.rs @@ -1,6 +1,6 @@ use codec::Encode; use subxt::config::ExtrinsicParams; -use subxt::{Config, PolkadotConfig, SubstrateConfig}; +use subxt::{Config}; pub enum StatemintConfig {} diff --git a/subxt/src/book/mod.rs b/subxt/src/book/mod.rs index 8ac867a614..5d321e1727 100644 --- a/subxt/src/book/mod.rs +++ b/subxt/src/book/mod.rs @@ -71,9 +71,9 @@ //! recent releases). Typically, to use Subxt to talk to some custom Substrate node (for example a //! parachain node), you'll want to: //! -//! 1. [Generate an interface](setup::codegen). -//! 2. [Create a Config](setup::config). -//! 2. [Use the config to instantiate the client](setup::client). +//! 1. [Generate an interface](setup::codegen) +//! 2. [Create a config](setup::config) +//! 2. [Use the config to instantiate the client](setup::client) //! //! Follow the above links to learn more about each step. //! diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index 938427f4d6..89eb566097 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -153,4 +153,4 @@ //! //! ```rust,ignore #![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_composed.rs")] -//! ``` \ No newline at end of file +//! ``` diff --git a/subxt/src/book/setup/mod.rs b/subxt/src/book/setup/mod.rs index d491a2e160..0d7a0b8922 100644 --- a/subxt/src/book/setup/mod.rs +++ b/subxt/src/book/setup/mod.rs @@ -11,4 +11,4 @@ pub mod client; pub mod codegen; -pub mod config; \ No newline at end of file +pub mod config; From d2ab721912bb97ad96923447b629894d0c6aa640 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Tue, 11 Jul 2023 14:11:57 +0200 Subject: [PATCH 15/28] fix doc ref --- subxt/src/book/setup/config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index 89eb566097..38bcca79a5 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -148,8 +148,7 @@ //! Statemint (Polkadot Asset Hub) seems to match the Polkadot config in almost all points, except for the `ExtrinsicParams`. //! Here the tips follow the same structure as for the default substrate node. //! We can now simply build the config for Statemint from the building blocks provided -//! by [subxt::SubstrateConfig] and [subxt::PolkadotConfig] as shown below. -//! +//! by [`PolkadotConfig`](crate::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig) as shown below. //! //! ```rust,ignore #![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_composed.rs")] From 75296e131d19fd69c2646a4337a5ba0d9bbadd4c Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Tue, 11 Jul 2023 15:32:20 +0200 Subject: [PATCH 16/28] fixing links to foreign crates --- subxt/src/book/setup/config.rs | 36 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index 38bcca79a5..3528ca80a9 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -27,22 +27,22 @@ //! We need to check, where the parachains runtime implements the frame_system::Config trait. //! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. //! For Statemint we find it [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179). -//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::Config] should also be the ones -//! we want to use for implementing [subxt::Config]. +//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) should also be the ones +//! we want to use for implementing [crate::Config]. //! In the Case of Statemint (Asset Hub) they are: //! //! - AccountId: [sp_core::crypto::AccountId32] //! - Index: [u32] //! - Hash: [sp_core::H256] -//! - Hasher (type `Hashing` in [frame_system::Config]): [sp_runtime::traits::BlakeTwo256] +//! - Hasher (type `Hashing` in [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html)): [sp_runtime::traits::BlakeTwo256] //! - Header: [sp_runtime::generic::Header](sp_runtime::generic::Header) //! //! ### Address, Signature, ExtrinsicParams -//! A Substrate runtime is typically constructed by using the [frame_support::construct_runtime] macro. +//! A Substrate runtime is typically constructed by using the [frame_support::construct_runtime](https://docs.rs/frame-support/latest/frame_support/macro.construct_runtime.html) macro. //! In this macro, we need to specify the type of an `UncheckedExtrinsic`. Most of the time, the `UncheckedExtrinsic` will be of the type //! [sp_runtime::generic::UncheckedExtrinsic](sp_runtime::generic::UncheckedExtrinsic). //! The generic parameters `Address` and `Signature` specified when declaring the `UncheckedExtrinsic` type -//! are the types for `Address` and `Signature` we should use when implementing the [subxt::Config] trait. +//! are the types for `Address` and `Signature` we should use when implementing the [crate::Config] trait. //! In case of Statemint (Polkadot Asset Hub) we see the following types being used in `UncheckedExtrinsic`: //! //! - Address: [sp_runtime::MultiAddress](sp_runtime::MultiAddress) @@ -72,20 +72,20 @@ //! signing a transaction and sent along with it, while _additional parameters_ are only used during //! the signing step but _not_ sent along with the transaction. //! -//! Each element of the `SignedExtra` tuple implements [parity_scale_codec::codec::Encode] and [sp_runtime::traits::SignedExtension] -//! which has an associated type `AdditionalSigned` that also implements [parity_scale_codec::codec::Encode]. Let's look at the underlying types for each tuple element. +//! Each element of the `SignedExtra` tuple implements [codec::Encode] and [sp_runtime::traits::SignedExtension] +//! which has an associated type `AdditionalSigned` that also implements [codec::Encode]. Let's look at the underlying types for each tuple element. //! All zero-sized types have been replaced by `()` for simplicity. //! //! | tuple element | struct type | `AdditionalSigned` type | //! | ------------------------------------ | ----------------------------------------------- | ---------------------------------| -//! | [frame_system::CheckNonZeroSender] | () | () | -//! | [frame_system::CheckSpecVersion] | () | [u32] | -//! | [frame_system::CheckTxVersion] | () | [u32] | -//! | [frame_system::CheckGenesis] | () | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckMortality] | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckNonce] | [Config::Index] = [u32] | () | -//! | [frame_system::CheckWeight] | () | () | -//! | [frame_system::ChargeAssetTxPayment] | [pallet_asset_tx_payment::ChargeAssetTxPayment] | () | +//! | [`frame_system::CheckNonZeroSender`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonZeroSender.html) | () | () | +//! | [frame_system::CheckSpecVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckSpecVersion.html) | () | [u32] | +//! | [frame_system::CheckTxVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckTxVersion.html) | () | [u32] | +//! | [frame_system::CheckGenesis](https://docs.rs/frame-system/latest/frame_system/struct.CheckGenesis.html) | () | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckMortality](https://docs.rs/frame-system/latest/frame_system/struct.CheckMortality.html) | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckNonce](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `Config::Index` = [u32] | () | +//! | [frame_system::CheckWeight](https://docs.rs/frame-system/latest/frame_system/struct.CheckWeight.html) | () | () | +//! | [frame_system::ChargeAssetTxPayment](https://docs.rs/frame-system/latest/frame_system/struct.ChargeAssetTxPayment.html) | [pallet_asset_tx_payment::ChargeAssetTxPayment](https://docs.rs/pallet-asset-tx-payment/latest/pallet_asset_tx_payment/struct.ChargeAssetTxPayment.html) | () | //! //! All types in the `struct type` column make up our _extra parameters_. //! We can put them together into a struct, ignoring all zero-sized types. @@ -103,8 +103,8 @@ //! especially because substrate crates and their types are quite big, clunky and entangled sometimes. //! //! With all these types collected, we can create two structs: `StatemintExtraParams` and `StatemintAdditionalParams`. -//! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [subxt::config::ExtrinsicParams] trait, see below. -//! Now we have all the parts we need to create our config `StatemintConfig` and implment the [subxt::Config] trait on it. +//! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [crate::config::ExtrinsicParams] trait, see below. +//! Now we have all the parts we need to create our config `StatemintConfig` and implment the [crate::Config] trait on it. //! Note that StatemintConfig is an empty enum, an _uninhabited type_ that is never means to be instantiated //! but just gives type information to various interfaces of _subxt_. //! @@ -129,7 +129,7 @@ //! - [crate::config::substrate::SubstrateHeader] instead of [sp_runtime::generic::Header] //! - [crate::config::substrate::AssetTip] and [crate::config::polkadot::PlainTip] instead of [pallet_transaction_payment::ChargeTransactionPayment](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/struct.ChargeTransactionPayment.html) //! - [crate::config::substrate::BlakeTwo256] instead of [sp_core::Blake2Hasher] or [sp_runtime::traits::BlakeTwo256] -//! - [crate::config::substrate::DigestItem] and [crate::config::substrate::Digest] instead of types from [sp_runtime::generic::digest] +//! - [crate::config::substrate::DigestItem] and [crate::config::substrate::Digest] instead of [sp_runtime::generic::Digest] and [sp_runtime::generic::DigestItem] //! - [crate::config::substrate::ConsensusEngineId] instead of [sp_runtime::ConsensusEngineId] //! //! With these optimizations, our config can look like this: From d600e49849f6163d22b07974efdbd69618b1b66f Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Tue, 11 Jul 2023 15:38:38 +0200 Subject: [PATCH 17/28] fix table formatting --- subxt/src/book/setup/config.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index 3528ca80a9..e6b7657428 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -76,15 +76,15 @@ //! which has an associated type `AdditionalSigned` that also implements [codec::Encode]. Let's look at the underlying types for each tuple element. //! All zero-sized types have been replaced by `()` for simplicity. //! -//! | tuple element | struct type | `AdditionalSigned` type | -//! | ------------------------------------ | ----------------------------------------------- | ---------------------------------| -//! | [`frame_system::CheckNonZeroSender`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonZeroSender.html) | () | () | -//! | [frame_system::CheckSpecVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckSpecVersion.html) | () | [u32] | -//! | [frame_system::CheckTxVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckTxVersion.html) | () | [u32] | -//! | [frame_system::CheckGenesis](https://docs.rs/frame-system/latest/frame_system/struct.CheckGenesis.html) | () | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckMortality](https://docs.rs/frame-system/latest/frame_system/struct.CheckMortality.html) | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckNonce](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `Config::Index` = [u32] | () | -//! | [frame_system::CheckWeight](https://docs.rs/frame-system/latest/frame_system/struct.CheckWeight.html) | () | () | +//! | tuple element | struct type | `AdditionalSigned` type | +//! | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +//! | [`frame_system::CheckNonZeroSender`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonZeroSender.html) | () | () | +//! | [frame_system::CheckSpecVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckSpecVersion.html) | () | [u32] | +//! | [frame_system::CheckTxVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckTxVersion.html) | () | [u32] | +//! | [frame_system::CheckGenesis](https://docs.rs/frame-system/latest/frame_system/struct.CheckGenesis.html) | () | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckMortality](https://docs.rs/frame-system/latest/frame_system/struct.CheckMortality.html) | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | +//! | [frame_system::CheckNonce](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `Config::Index` = [u32] | () | +//! | [frame_system::CheckWeight](https://docs.rs/frame-system/latest/frame_system/struct.CheckWeight.html) | () | () | //! | [frame_system::ChargeAssetTxPayment](https://docs.rs/frame-system/latest/frame_system/struct.ChargeAssetTxPayment.html) | [pallet_asset_tx_payment::ChargeAssetTxPayment](https://docs.rs/pallet-asset-tx-payment/latest/pallet_asset_tx_payment/struct.ChargeAssetTxPayment.html) | () | //! //! All types in the `struct type` column make up our _extra parameters_. From 33e29f24e144c9e6ee0937d1de4bb43a3a6bd37d Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Mon, 17 Jul 2023 13:49:17 +0200 Subject: [PATCH 18/28] include nits --- .gitignore | 2 +- examples/parachain-example/Cargo.toml | 2 +- examples/parachain-example/examples/create_nft.rs | 2 +- subxt/src/book/mod.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index e7dc82d631..b92643636e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ cargo-timing* /examples/wasm-example/dist /examples/wasm-example/target /examples/parachain-example/target -/examples/parachain-example/metadata/target \ No newline at end of file +/examples/parachain-example/metadata/target diff --git a/examples/parachain-example/Cargo.toml b/examples/parachain-example/Cargo.toml index 82675aee91..929acf6578 100644 --- a/examples/parachain-example/Cargo.toml +++ b/examples/parachain-example/Cargo.toml @@ -14,4 +14,4 @@ sp-core = "21.0.0" sp-runtime = "24.0.0" codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } scale-decode = "0.7.0" -scale-encode = "0.3.0" \ No newline at end of file +scale-encode = "0.3.0" diff --git a/examples/parachain-example/examples/create_nft.rs b/examples/parachain-example/examples/create_nft.rs index 84857fdb7c..4e7fb1a9c0 100644 --- a/examples/parachain-example/examples/create_nft.rs +++ b/examples/parachain-example/examples/create_nft.rs @@ -58,7 +58,7 @@ //! //! In this example we use the _uniques_ pallet of the polkadot asset hub parachain. //! The dev account _alice_ creates an NFT collection, then mints an NFT that is part of the collection. -//! Beware that this example can take up to a minute to run. Specify the port like so: +//! Beware that this example can take up to a minute to run. //! ```txt //! cargo run --bin submit_transaction //! ``` diff --git a/subxt/src/book/mod.rs b/subxt/src/book/mod.rs index 5d321e1727..a729532ab7 100644 --- a/subxt/src/book/mod.rs +++ b/subxt/src/book/mod.rs @@ -73,7 +73,7 @@ //! //! 1. [Generate an interface](setup::codegen) //! 2. [Create a config](setup::config) -//! 2. [Use the config to instantiate the client](setup::client) +//! 3. [Use the config to instantiate the client](setup::client) //! //! Follow the above links to learn more about each step. //! From a9901a51f59abd0cf1c2786856ade1609054c8c5 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 18 Jul 2023 18:14:07 +0100 Subject: [PATCH 19/28] move more docs to book, and simplify parachain-example --- examples/parachain-example/README.md | 80 +++++++ .../parachain-example/examples/create_nft.rs | 141 ------------ .../examples/fetch_blocks.rs | 64 ------ examples/parachain-example/src/lib.rs | 51 ----- examples/parachain-example/src/main.rs | 94 ++++++++ .../src/statemint_config_composed.rs | 17 -- .../src/statemint_config_with_subxt_types.rs | 79 ------- examples/wasm-example/README.md | 23 ++ examples/wasm-example/src/main.rs | 12 -- .../examples/setup_config_custom.rs | 84 ++++---- subxt/src/book/setup/config.rs | 200 +++++++++--------- 11 files changed, 347 insertions(+), 498 deletions(-) create mode 100644 examples/parachain-example/README.md delete mode 100644 examples/parachain-example/examples/create_nft.rs delete mode 100644 examples/parachain-example/examples/fetch_blocks.rs delete mode 100644 examples/parachain-example/src/lib.rs create mode 100644 examples/parachain-example/src/main.rs delete mode 100644 examples/parachain-example/src/statemint_config_composed.rs delete mode 100644 examples/parachain-example/src/statemint_config_with_subxt_types.rs create mode 100644 examples/wasm-example/README.md rename examples/parachain-example/src/statemint_config_verbose.rs => subxt/examples/setup_config_custom.rs (59%) diff --git a/examples/parachain-example/README.md b/examples/parachain-example/README.md new file mode 100644 index 0000000000..988e678bda --- /dev/null +++ b/examples/parachain-example/README.md @@ -0,0 +1,80 @@ +# parachain-example + +This example showcases working with Subxt and Zombienet to try out connecting to a locally deployed parachain, here +["Statemint"](https://parachains.info/details/statemint), also known as "Asset Hub". + +## Running the example + +### 1. Install `zombienet` + +[Zombienet](https://github.com/paritytech/zombienet) is a tool for quickly spinning up a (local) blockchain +network. We will use it to start up a local Asset Hub for us. + +Please follow the install guide in the [zombienet github repo](https://github.com/paritytech/zombienet) to +install it. + +### 2. `polkadot` + +We need a relay chain. Build the polkadot binary from the [polkadot github repo](https://github.com/paritytech/polkadot) +and install it in your path: + +```txt +git clone https://github.com/paritytech/polkadot.git +cd polkadot +cargo build --release +cargo install --path . +``` + +### 3. `polkadot-parachain` + +The Asset Hub is part of the [cumulus github repo](https://github.com/paritytech/cumulus), an SDK for developing +parachains. Building the cumulus workspace produces a binary called `polkadot-parachain` which can be used to run +Asset Hub nodes. + +```txt +git clone https://github.com/paritytech/cumulus.git +cd cumulus +cargo build --release +cargo install --path . +``` + +### 4. Run the parachain locally + +With these binaries installed, Zombienet can now get the parachain running locally from a configuration file, `asset-hub-zombienet.toml` +in this case. We need to have at least 2 validator nodes running via the `polkadot` binary, and an Asset Hub node running via the +`polkadot-parachain` binary. Zombienet starts these up, and gets the parachain registered with the validator nodes for us. To do that, +run: + +```txt +zombienet -p native spawn asset-hub-zombienet.toml +``` + +Zombienet uses Kubernetes by default, but we can use it without Kubernetes by providing the `-p native` flag. + +You might have noticed that we use `chain = "rococo-local"` in the `asset-hub-zombienet.toml` file for the relay chain. This is just to +make the epoch time shorter and should have no effect on your interactions with the parachain. Polkadot / Kusama / Rococo have different +epoch times of `24h` / `2h` / `2min` respectively. + +### 5. Run the example + +The parachain is only registered after the first epoch. So after the previous step, we need to wait 2 minutes until the parachain becomes +interactive and produces blocks. At this point, we can run: + +``` +cargo run --bin +``` + +To run our example code. + +## Dev notes + +We can obtain the metadata for Statemint via the [subxt cli](https://crates.io/crates/subxt-cli) tool, like so: + +```txt +subxt metadata --url wss://polkadot-asset-hub-rpc.polkadot.io:443 > statemint_metadata.scale +``` + +It is important to explicitly specify the port as `443`. + +One way to find a suitable URL to obtain this from is by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/) +to find the Asset Hub entry, and seeing which RPC node URLs it uses. diff --git a/examples/parachain-example/examples/create_nft.rs b/examples/parachain-example/examples/create_nft.rs deleted file mode 100644 index 4e7fb1a9c0..0000000000 --- a/examples/parachain-example/examples/create_nft.rs +++ /dev/null @@ -1,141 +0,0 @@ -//! In this example we want to submit a transaction to the asset hub parachain. -//! Doing so on the official polkadot network, would require us to have an account with sufficient funds. -//! That is why we spawn a local asset hub parachain instead, that comes with pre-funded dev accounts. -//! -//! # Setting up the local parachain -//! -//! We use [zombienet](https://github.com/paritytech/zombienet) to start up a local asset hub. -//! -//! ## 1. Install necessary tools -//! -//! To setup the local parachain we need to have 3 binaries installed in our path: -//! -//! ### 1. `zombienet` -//! -//! Zombienet is a tool for quickly spinning up a (local) blockchain network. Please follow the install guide in the [zombienet github repo](https://github.com/paritytech/zombienet). -//! -//! ### 2. `polkadot` -//! -//! Build the polkadot binary from the [polkadot github repo](https://github.com/paritytech/polkadot) and install it in your path: -//! ```txt -//! git clone https://github.com/paritytech/polkadot.git -//! cd polkadot -//! cargo build --release -//! cargo install --path . -//! ``` -//! -//! ### 3. `polkadot-parachain` -//! -//! The polkadot asset hub is part of the [cumulus github repo](https://github.com/paritytech/cumulus), an SDK for developing parachains. -//! Building the cumulus workspace produces a binary called `polkadot-parachain` that has the capability and configuration data to run the asset hub. -//! ```txt -//! git clone https://github.com/paritytech/cumulus.git -//! cd cumulus -//! cargo build --release -//! cargo install --path . -//! ``` -//! -//! ## 2. Run the parachain locally -//! -//! Zombienet can now spawn the parachain locally from a configuration file, `asset-hub-zombienet.toml` in this case. -//! We need to have at least 2 validator nodes running (via the `polkadot` binary), -//! while the `polkadot-parachain` binary starts the asset hub parachain and gets it registered with the validator nodes. -//! To do that, run: -//! ```txt -//! zombienet -p native spawn asset-hub-zombienet.toml -//! ``` -//! Zombienet uses Kubernetes by default, but we can use it without Kubernetes, by providing the `-p native` flag. -//! -//! You might have noticed, that we use `chain = "rococo-local"` in the `asset-hub-zombienet.toml` file for the relay chain. -//! This is just to make the epoch time shorter and should have no effect on your interactions with the parachain. -//! Polkadot / Kusama / Rococo have different epoch times of `24h` / `2h` / `2min` respectively. -//! The parachain is only registered after the first epoch. So we need to wait 2 minutes, until the parachain becomes interactive and produces blocks. -//! -//! # Running the example -//! -//! After you have the network up and running, you should see something like [https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:42069#/explorer] -//! as the polkadot.js link to the parachain (e.g. "collator01") in the zombienet output. -//! -//! In this example we use the _uniques_ pallet of the polkadot asset hub parachain. -//! The dev account _alice_ creates an NFT collection, then mints an NFT that is part of the collection. -//! Beware that this example can take up to a minute to run. -//! ```txt -//! cargo run --bin submit_transaction -//! ``` -//! - -use parachain_example::statemint; -use parachain_example::statemint_config_composed::StatemintConfig; -use subxt::{ - utils::{AccountId32, MultiAddress}, - OnlineClient, -}; - -use subxt_signer::sr25519::dev::{self}; - -/// cargo run --bin submit_transaction -#[tokio::main] -pub async fn main() { - if let Err(err) = run().await { - eprintln!("{err}"); - } -} - -async fn run() -> Result<(), Box> { - // (the port 42069 is specified in the asset-hub-zombienet.toml) - let api = OnlineClient::::from_url("ws://127.0.0.1:42069").await?; - println!("Connection with parachain established."); - let alice: MultiAddress = dev::alice().public_key().into(); - let alice_pair_signer = dev::alice(); - - const COLLECTION_ID: u32 = 12; - const NTF_ID: u32 = 234; - - // create a collection with id `42` - let collection_creation_tx = statemint::tx() - .uniques() - .create(COLLECTION_ID, alice.clone()); - let _collection_creation_events = api - .tx() - .sign_and_submit_then_watch_default(&collection_creation_tx, &alice_pair_signer) - .await - .map(|e| { - println!("Collection creation submitted, waiting for transaction to be finalized..."); - e - })? - .wait_for_finalized_success() - .await?; - println!("Collection created."); - - // create an nft in that collection with id `420` - let nft_creation_tx = statemint::tx() - .uniques() - .mint(COLLECTION_ID, NTF_ID, alice.clone()); - let _nft_creation_events = api - .tx() - .sign_and_submit_then_watch_default(&nft_creation_tx, &alice_pair_signer) - .await - .map(|e| { - println!("NFT creation submitted, waiting for transaction to be finalized..."); - e - })? - .wait_for_finalized_success() - .await?; - println!("NFT created."); - - // check in storage, that alice is the official owner of the NFT: - let nft_owner_storage_query = statemint::storage().uniques().asset(COLLECTION_ID, NTF_ID); - let nft_storage_details = api - .storage() - .at_latest() - .await? - .fetch(&nft_owner_storage_query) - .await? - .ok_or("The NFT should have an owner (alice)")?; - - // make sure that alice is the owner of the NFT: - assert_eq!(nft_storage_details.owner, dev::alice().public_key().into()); - println!("Storage Item Details: {:?}", nft_storage_details); - - Ok(()) -} diff --git a/examples/parachain-example/examples/fetch_blocks.rs b/examples/parachain-example/examples/fetch_blocks.rs deleted file mode 100644 index bf4d6f417b..0000000000 --- a/examples/parachain-example/examples/fetch_blocks.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! In this example we connect to the official polkadot asset hub parachain and subscribe to blocks that get produced. -//! You can just switch out `StatemintConfig` for `StatemintConfigWithSubxtTypes` or `StatemintConfigComposed` and the behavior should be the same. -//! -//! To run this example: -//! ```txt -//! cargo run --bin fetch_blocks -//! ``` - -use parachain_example::statemint; -use futures::StreamExt; -use parachain_example::statemint_config_composed::StatemintConfig; -use subxt::OnlineClient; - -/// cargo run --bin fetch_blocks -#[tokio::main] -async fn main() -> Result<(), Box> { - let rpc_endpoint = "wss://polkadot-asset-hub-rpc.polkadot.io:443"; - - // here we use the config: - let api = OnlineClient::::from_url(rpc_endpoint).await?; - - // Subscribe to all finalized blocks: - let mut blocks_sub = api.blocks().subscribe_finalized().await?; - - // For each block, print a bunch of information about it: - while let Some(block) = blocks_sub.next().await { - let block = block?; - - let block_number = block.header().number; - let block_hash = block.hash(); - - println!("Block #{block_number}:"); - println!(" Hash: {block_hash}"); - println!(" Extrinsics:"); - - let body = block.body().await?; - for ext in body.extrinsics().iter() { - let ext = ext?; - let idx = ext.index(); - let events = ext.events().await?; - - // here we make use of the generated metadata code: - let decoded_ext = ext.as_root_extrinsic::(); - - println!(" Extrinsic #{idx}:"); - println!(" Bytes: {}", ext.bytes().len()); - println!(" Decoded: {decoded_ext:?}"); - println!(" Events:"); - - for evt in events.iter() { - let evt = evt?; - - let pallet_name = evt.pallet_name(); - let event_name = evt.variant_name(); - let event_values = evt.field_values()?; - - println!(" {pallet_name}_{event_name}"); - println!(" {}", event_values); - } - } - } - - Ok(()) -} diff --git a/examples/parachain-example/src/lib.rs b/examples/parachain-example/src/lib.rs deleted file mode 100644 index b3380040ba..0000000000 --- a/examples/parachain-example/src/lib.rs +++ /dev/null @@ -1,51 +0,0 @@ -//! # Tutorial: Subxt setup to interact with custom chains -//! -//! There are many parachains on Polkadot and Kusama. Using Subxt to connect to a parachain -//! (or any other custom, substrate based chain) requires 2 steps: -//! -//! 1. Fetching the chains metadata to generate a static interface via the subxt codegen. -//! 2. Creating a config struct that implements `subxt::Config` to give some type information -//! that is currently not covered by the metadata. -//! -//! This example shows you how to connect to the ["Statemint"](https://parachains.info/details/statemint) parachain, -//! also known as "Asset Hub", both locally and remotely. -//! -//! ### Example 1: Subscribe to blocks of the official ["Polkadot Asset Hub"](https://parachains.info/details/statemint) -//! -//! ``` -//! cargo run --example fetch_blocks.rs -//! ``` -//! -//! ### Example 2: Create an NFT on a local parachain -//! -//! This requires you to spin up a local asset hub parachain using Zombienet. Please see the instructions in the example. -//! ``` -//! cargo run --example create_nft.rs -//! ``` -//! -//! # How to get the parachains metadata -//! -//! To fetch the metadata for the Statemint parachain, we need to have the URL of an RPC node. -//! We can find the "Asset Hub" entry, by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/). -//! We connect to the node ("via Parity"), which leads us to [this page](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot-asset-hub-rpc.polkadot.io#/explorer). -//! In the URL of the page we can already see the URL of the RPC endpoint of the node as a query parameter. It is also printed -//! to the Javascript console of the browser: `WS endpoint= wss://polkadot-asset-hub-rpc.polkadot.io`. -//! -//! We can now get the metadata via the [subxt cli](https://crates.io/crates/subxt-cli) tool. -//! It is important to specify the port as `:443` like so: -//! ```txt -//! subxt metadata --url wss://polkadot-asset-hub-rpc.polkadot.io:443 > statemint_metadata.scale -//! ``` -//! The metadata is saved as `statemint_metadata.scale` and can be used to create the statically generated interface for the parachain: -//! ``` -//! #[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] -//! pub mod statemint {} -//! ``` -//! - -pub mod statemint_config_composed; -pub mod statemint_config_verbose; -pub mod statemint_config_with_subxt_types; - -#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] -pub mod statemint {} diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs new file mode 100644 index 0000000000..38ad9dde77 --- /dev/null +++ b/examples/parachain-example/src/main.rs @@ -0,0 +1,94 @@ +#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] +pub mod statemint {} + +use parachain_example::statemint; +use parachain_example::statemint_config_composed::StatemintConfig; +use subxt::{ + Config, PolkadotConfig, SubstrateConfig, + utils::{AccountId32, MultiAddress}, + OnlineClient, +}; + +use subxt_signer::sr25519::dev::{self}; + +/// Custom config that works with Statemint: +pub enum StatemintConfig {} + +impl Config for StatemintConfig { + type Index = ::Index; + type Hash = ::Hash; + type AccountId = ::AccountId; + type Address = ::Address; + type Signature = ::Signature; + type Hasher = ::Hasher; + type Header = ::Header; + type ExtrinsicParams = ::ExtrinsicParams; +} + + +#[tokio::main] +pub async fn main() { + if let Err(err) = run().await { + eprintln!("{err}"); + } +} + +async fn run() -> Result<(), Box> { + // (the port 42069 is specified in the asset-hub-zombienet.toml) + let api = OnlineClient::::from_url("ws://127.0.0.1:42069").await?; + println!("Connection with parachain established."); + + let alice: MultiAddress = dev::alice().public_key().into(); + let alice_pair_signer = dev::alice(); + + const COLLECTION_ID: u32 = 12; + const NTF_ID: u32 = 234; + + // create a collection with id `42` + let collection_creation_tx = statemint::tx() + .uniques() + .create(COLLECTION_ID, alice.clone()); + let _collection_creation_events = api + .tx() + .sign_and_submit_then_watch_default(&collection_creation_tx, &alice_pair_signer) + .await + .map(|e| { + println!("Collection creation submitted, waiting for transaction to be finalized..."); + e + })? + .wait_for_finalized_success() + .await?; + println!("Collection created."); + + // create an nft in that collection with id `420` + let nft_creation_tx = statemint::tx() + .uniques() + .mint(COLLECTION_ID, NTF_ID, alice.clone()); + let _nft_creation_events = api + .tx() + .sign_and_submit_then_watch_default(&nft_creation_tx, &alice_pair_signer) + .await + .map(|e| { + println!("NFT creation submitted, waiting for transaction to be finalized..."); + e + })? + .wait_for_finalized_success() + .await?; + println!("NFT created."); + + // check in storage, that alice is the official owner of the NFT: + let nft_owner_storage_query = statemint::storage().uniques().asset(COLLECTION_ID, NTF_ID); + let nft_storage_details = api + .storage() + .at_latest() + .await? + .fetch(&nft_owner_storage_query) + .await? + .ok_or("The NFT should have an owner (alice)")?; + + // make sure that alice is the owner of the NFT: + assert_eq!(nft_storage_details.owner, dev::alice().public_key().into()); + println!("Storage Item Details: {:?}", nft_storage_details); + + Ok(()) +} diff --git a/examples/parachain-example/src/statemint_config_composed.rs b/examples/parachain-example/src/statemint_config_composed.rs deleted file mode 100644 index f18fbc630e..0000000000 --- a/examples/parachain-example/src/statemint_config_composed.rs +++ /dev/null @@ -1,17 +0,0 @@ - - -use subxt::{Config, PolkadotConfig, SubstrateConfig}; - -pub enum StatemintConfig {} - -impl Config for StatemintConfig { - type Index = ::Index; - type Hash = ::Hash; - type AccountId = ::AccountId; - type Address = ::Address; - type Signature = ::Signature; - type Hasher = ::Hasher; - type Header = ::Header; - // this is the only difference to the PolkadotConfig: - type ExtrinsicParams = ::ExtrinsicParams; -} diff --git a/examples/parachain-example/src/statemint_config_with_subxt_types.rs b/examples/parachain-example/src/statemint_config_with_subxt_types.rs deleted file mode 100644 index 8706e7b2c3..0000000000 --- a/examples/parachain-example/src/statemint_config_with_subxt_types.rs +++ /dev/null @@ -1,79 +0,0 @@ -use codec::Encode; -use subxt::config::ExtrinsicParams; -use subxt::{Config}; - -pub enum StatemintConfig {} - -impl Config for StatemintConfig { - type Index = u32; - type Hash = subxt::utils::H256; - type AccountId = subxt::utils::AccountId32; - type Address = subxt::utils::MultiAddress; - type Signature = subxt::utils::MultiSignature; - type Hasher = subxt::config::substrate::BlakeTwo256; - type Header = subxt::config::substrate::SubstrateHeader; - type ExtrinsicParams = StatemintExtrinsicParams; -} - -#[derive(Encode, Debug, Clone)] -pub struct StatemintExtrinsicParams { - extra_params: StatemintExtraParams, - additional_params: StatemintAdditionalParams, -} - -#[derive(Encode, Debug, Clone)] -pub struct StatemintExtraParams { - era: subxt::config::extrinsic_params::Era, - nonce: u32, - charge: subxt::config::substrate::AssetTip, -} - -#[derive(Encode, Debug, Clone)] -pub struct StatemintAdditionalParams { - spec_version: u32, - tx_version: u32, - genesis_hash: subxt::utils::H256, - mortality_hash: subxt::utils::H256, -} - -impl ExtrinsicParams<::Index, ::Hash> -for StatemintExtrinsicParams -{ - /// mortality hash, era, charge - type OtherParams = ( - subxt::utils::H256, - subxt::config::extrinsic_params::Era, - subxt::config::substrate::AssetTip, - ); - - fn new( - spec_version: u32, - tx_version: u32, - nonce: ::Index, - genesis_hash: ::Hash, - other_params: Self::OtherParams, - ) -> Self { - let (mortality_hash, era, charge) = other_params; - - let extra_params = StatemintExtraParams { era, nonce, charge }; - - let additional_params = StatemintAdditionalParams { - spec_version, - tx_version, - genesis_hash, - mortality_hash, - }; - Self { - extra_params, - additional_params, - } - } - - fn encode_extra_to(&self, v: &mut Vec) { - self.extra_params.encode_to(v); - } - - fn encode_additional_to(&self, v: &mut Vec) { - self.additional_params.encode_to(v); - } -} diff --git a/examples/wasm-example/README.md b/examples/wasm-example/README.md new file mode 100644 index 0000000000..b930f6f09f --- /dev/null +++ b/examples/wasm-example/README.md @@ -0,0 +1,23 @@ +# wasm-example + +This is a small WASM app using the Yew UI framework to showcase how to use Subxt's features in a WASM environment. + +To run the app locally we first install Trunk, a WASM bundler: + +``` +cargo install --locked trunk +``` + +You need to have a local polkadot/substrate node with it's JSON-RPC HTTP server running at 127.0.0.1:9933 in order for the examples to be working. +If you have a `polkadot` binary already, running this should be sufficient: + +``` +polkadot --dev +``` + +Then, in another terminal, run the app locally with: + +``` +trunk serve --open +``` + diff --git a/examples/wasm-example/src/main.rs b/examples/wasm-example/src/main.rs index 6ece80e462..522109f988 100644 --- a/examples/wasm-example/src/main.rs +++ b/examples/wasm-example/src/main.rs @@ -1,15 +1,3 @@ -//! This is a small WASM app using the Yew UI framework showcasing how to use Subxt's features in a WASM environment. -//! -//! To run the app locally use Trunk, a WASM bundler: -//! ``` -//! cargo install --locked trunk -//! ``` -//! Run the app locally: -//! ``` -//! trunk serve --open -//! ``` -//! You need to have a local polkadot/substrate node with it's JSON-RPC HTTP server running at 127.0.0.1:9933 in order for the examples to be working. -//! Also make sure your browser supports WASM. use futures::{self, FutureExt}; use yew::prelude::*; diff --git a/examples/parachain-example/src/statemint_config_verbose.rs b/subxt/examples/setup_config_custom.rs similarity index 59% rename from examples/parachain-example/src/statemint_config_verbose.rs rename to subxt/examples/setup_config_custom.rs index 5c4312bfe9..c2df705694 100644 --- a/examples/parachain-example/src/statemint_config_verbose.rs +++ b/subxt/examples/setup_config_custom.rs @@ -1,17 +1,19 @@ use codec::Encode; -use subxt::config::ExtrinsicParams; -use subxt::{Config}; +use primitive_types::H256; +use subxt::config::{Config, ExtrinsicParams}; +// We don't need to construct this at runtime, +// so an empty enum is appropriate: pub enum StatemintConfig {} impl Config for StatemintConfig { type Index = u32; - type Hash = sp_core::H256; - type AccountId = sp_core::crypto::AccountId32; - type Address = sp_runtime::MultiAddress; - type Signature = sp_runtime::MultiSignature; - type Hasher = sp_runtime::traits::BlakeTwo256; - type Header = sp_runtime::generic::Header; + type Hash = subxt::utils::H256; + type AccountId = subxt::utils::AccountId32; + type Address = subxt::utils::MultiAddress; + type Signature = subxt::utils::MultiSignature; + type Hasher = subxt::config::substrate::BlakeTwo256; + type Header = subxt::config::substrate::SubstrateHeader; type ExtrinsicParams = StatemintExtrinsicParams; } @@ -21,68 +23,74 @@ pub struct StatemintExtrinsicParams { additional_params: StatemintAdditionalParams, } -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct StatemintExtraParams { - era: sp_runtime::generic::Era, - nonce: u32, - charge: ChargeAssetTxPayment, -} - -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct ChargeAssetTxPayment { - #[codec(compact)] - tip: u128, - asset_id: Option, -} - -#[derive(Encode, Debug, Clone, Eq, PartialEq)] -pub struct StatemintAdditionalParams { - spec_version: u32, - tx_version: u32, - genesis_hash: sp_core::H256, - mortality_hash: sp_core::H256, -} - -impl ExtrinsicParams<::Index, ::Hash> -for StatemintExtrinsicParams -{ - /// mortality hash, era, charge +impl ExtrinsicParams for StatemintExtrinsicParams { + // We need these additional values that aren't otherwise + // provided. Calls like api.tx().sign_and_submit_then_watch() + // allow the user to provide an instance of these, so it's wise + // to give this a nicer interface in reality: type OtherParams = ( sp_core::H256, sp_runtime::generic::Era, ChargeAssetTxPayment, ); + // Gather together all of the params we will need to encode: fn new( spec_version: u32, tx_version: u32, - nonce: ::Index, - genesis_hash: ::Hash, + nonce: u32, + genesis_hash: H256, other_params: Self::OtherParams, ) -> Self { let (mortality_hash, era, charge) = other_params; let extra_params = StatemintExtraParams { era, nonce, charge }; - let additional_params = StatemintAdditionalParams { spec_version, tx_version, genesis_hash, mortality_hash, }; + Self { extra_params, additional_params, } } + // Encode the relevant params when asked: fn encode_extra_to(&self, v: &mut Vec) { self.extra_params.encode_to(v); } - fn encode_additional_to(&self, v: &mut Vec) { self.additional_params.encode_to(v); } } +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintExtraParams { + era: sp_runtime::generic::Era, + nonce: u32, + charge: ChargeAssetTxPayment, +} +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct ChargeAssetTxPayment { + #[codec(compact)] + tip: u128, + asset_id: Option, +} + +#[derive(Encode, Debug, Clone, Eq, PartialEq)] +pub struct StatemintAdditionalParams { + spec_version: u32, + tx_version: u32, + genesis_hash: sp_core::H256, + mortality_hash: sp_core::H256, +} + +#[tokio::main] +async fn main() { + // With the config defined, it can be handed to Subxt as follows: + let _client_fut = subxt::OnlineClient::::new(); +} diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index e6b7657428..85f93e584f 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -9,35 +9,49 @@ //! //! # How to create a Config for a custom chain? //! -//! We now show in depth how a subxt Config can be created for a parachain, using the ["Statemint"](https://parachains.info/details/statemint) parachain, -//! also known as "Asset Hub" as an example. It is currently (as of 2023-06-26) -//! deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). -//! We also provide a separate example on [how to interact with the parachain](https://github.com/paritytech/subxt/tree/master/examples/parachain-example). +//! Some chains may use config that is not compatible with our [`PolkadotConfig`](crate::config::PolkadotConfig) or +//! [`SubstrateConfig`](crate::config::SubstrateConfig). +//! +//! We now walk through how a subxt [`crate::config::Config`] can be created for a parachain, using the +//! ["Statemint"](https://parachains.info/details/statemint) parachain, also known as "Asset Hub" as an example. It +//! is currently (as of 2023-06-26) deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). //! //! To construct a config, we need to investigate which types Statemint uses as `AccountId`, `Hasher`, etc. //! We need to take a look at the source code of Statemint and find out how it implements some substrate functionalities. //! Statemint (Polkadot Asset Hub) is part of the [Cumulus Github repository](https://github.com/paritytech/cumulus). //! The crate defining the parachains runtime can be found [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot). //! -//! ## 1. Create the config from scratch +//! ## Creating the `Config` from scratch //! -//! First we want to create the config from scratch to understand all the details. +//! Creating the config from scratch is the most arduous approach but also the most flexible, so first we'll walk through +//! how to do this, and then we'll show how to simplify the process, which can be achieved in most cases. //! //! ### AccountId, Index, Hash, Hasher and Header -//! We need to check, where the parachains runtime implements the frame_system::Config trait. +//! +//! For these config types, we need to find out where the parachain runtime implements the `frame_system::Config` trait. //! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. //! For Statemint we find it [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179). -//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) should also be the ones -//! we want to use for implementing [crate::Config]. -//! In the Case of Statemint (Asset Hub) they are: +//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) +//! should also be the ones we want to use for implementing [crate::Config]. In the Case of Statemint (Asset Hub) they are: +//! +//! - AccountId: [`sp_core::crypto::AccountId32`] +//! - Index: [`u32`] +//! - Hash: [`sp_core::H256`] +//! - Hasher (type `Hashing` in [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html)): [`sp_runtime::traits::BlakeTwo256`] +//! - Header: [`sp_runtime::generic::Header`](sp_runtime::generic::Header) +//! +//! Subxt has its own versions of some of these types in order to avoid needing to pull in Substrate dependencies: +//! +//! - [`sp_core::crypto::AccountId32`] can be swapped with [`crate::utils::AccountId32`]. +//! - [`sp_core::H256`] is a re-export which subxt also provides as [`crate::config::substrate::H256`]. +//! - [`sp_runtime::traits::BlakeTwo256`] can be swapped with [`crate::config::substrate::BlakeTwo256`]. +//! - [`sp_runtime::generic::Header`] can be swapped with [`crate::config::substrate::SubstrateHeader`]. //! -//! - AccountId: [sp_core::crypto::AccountId32] -//! - Index: [u32] -//! - Hash: [sp_core::H256] -//! - Hasher (type `Hashing` in [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html)): [sp_runtime::traits::BlakeTwo256] -//! - Header: [sp_runtime::generic::Header](sp_runtime::generic::Header) +//! Having a look at how those types are implemented can give some clues as to how to implement other custom types that +//! you may need to use as part of your config. +//! +//! ### Address, Signature //! -//! ### Address, Signature, ExtrinsicParams //! A Substrate runtime is typically constructed by using the [frame_support::construct_runtime](https://docs.rs/frame-support/latest/frame_support/macro.construct_runtime.html) macro. //! In this macro, we need to specify the type of an `UncheckedExtrinsic`. Most of the time, the `UncheckedExtrinsic` will be of the type //! [sp_runtime::generic::UncheckedExtrinsic](sp_runtime::generic::UncheckedExtrinsic). @@ -48,11 +62,29 @@ //! - Address: [sp_runtime::MultiAddress](sp_runtime::MultiAddress) //! - Signature: [sp_runtime::MultiSignature] //! -//! #### ExtrinsicParams -//! The `ExtrinsicParams` type is the most complicated to set up, but it can be derived from -//! the `SignedExtra` parameter of the `UncheckedExtrinsic` of your parachain. The `SignedExtra` parameter is a tuple in most cases, -//! where each field of the tuple corresponds to 0-1 fields in the `ExtrinsicParams` struct we want to create. -//! It looks like [this](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L779) for the Statemint parachain: +//! As above, Subxt has its own versions of these types that can be used instead to avoid pulling in Substrate dependencies. +//! Using the Subxt versions also makes interacting with generated code (which uses them in some places) a little nicer: +//! +//! - [`sp_runtime::MultiAddress`] can be swapped with [`crate::utils::MultiAddress`]. +//! - [`sp_runtime::MultiSignature`] can be swapped with [`crate::utils::MultiSignature`]. +//! +//! ### ExtrinsicParams +//! +//! Parachains each have a set of "signed extensions" configured. Signed extensions provide a means to extend how transactions +//! work. Each signed extension can potentially encode some "extra" data which is sent along with a transaction, as well as some +//! "additional" data which is included in the transaction signer payload, but not transmitted along with the transaction. +//! +//! The `ExtrinsicParams` config type expects to be given an implementation of the [`crate::config::ExtrinsicParams`] trait. +//! Implementations of the [`crate::config::ExtrinsicParams`] trait are handed some parameters from Subxt itself, and can +//! accept arbitrary `OtherParams` from users, and are then expected to provide this "extra" and "additional" data when asked. +//! +//! In order to construct a valid implementation of the `ExtrinsicParams` trait, you must first find out which signed extensions +//! are in use by a chain. This information can be obtained from the `SignedExtra` parameter of the `UncheckedExtrinsic` of your +//! parachain, which will be a tuple of signed extensions. It can also be obtained from the metadata (see +//! [`frame_metadata::v15::SignedExtensionMetadata`]). +//! +//! For statemint, the signed extensions look like +//! [this](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L779): //! //! ```rs //! pub type SignedExtra = ( @@ -67,89 +99,65 @@ //! ); //! ``` //! -//! The `ExtrinsicParams` struct is basically a collection of fields that can be grouped into two categories: -//! _extra parameters_ and _additional parameters_. _Extra parameters_ are taken into account when -//! signing a transaction and sent along with it, while _additional parameters_ are only used during -//! the signing step but _not_ sent along with the transaction. -//! //! Each element of the `SignedExtra` tuple implements [codec::Encode] and [sp_runtime::traits::SignedExtension] -//! which has an associated type `AdditionalSigned` that also implements [codec::Encode]. Let's look at the underlying types for each tuple element. -//! All zero-sized types have been replaced by `()` for simplicity. -//! -//! | tuple element | struct type | `AdditionalSigned` type | -//! | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -//! | [`frame_system::CheckNonZeroSender`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonZeroSender.html) | () | () | -//! | [frame_system::CheckSpecVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckSpecVersion.html) | () | [u32] | -//! | [frame_system::CheckTxVersion](https://docs.rs/frame-system/latest/frame_system/struct.CheckTxVersion.html) | () | [u32] | -//! | [frame_system::CheckGenesis](https://docs.rs/frame-system/latest/frame_system/struct.CheckGenesis.html) | () | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckMortality](https://docs.rs/frame-system/latest/frame_system/struct.CheckMortality.html) | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | -//! | [frame_system::CheckNonce](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `Config::Index` = [u32] | () | -//! | [frame_system::CheckWeight](https://docs.rs/frame-system/latest/frame_system/struct.CheckWeight.html) | () | () | -//! | [frame_system::ChargeAssetTxPayment](https://docs.rs/frame-system/latest/frame_system/struct.ChargeAssetTxPayment.html) | [pallet_asset_tx_payment::ChargeAssetTxPayment](https://docs.rs/pallet-asset-tx-payment/latest/pallet_asset_tx_payment/struct.ChargeAssetTxPayment.html) | () | -//! -//! All types in the `struct type` column make up our _extra parameters_. -//! We can put them together into a struct, ignoring all zero-sized types. -//! The types of the last column make up our _additional parameters_. Here -//! we can also ignore the zero-sized types. We can name the fields however we like, -//! however their order in the struct should match the order in the `SignedExtra` tuple (see table). -//! Beware that some numbers might be compact encoded, when encoding the struct, some might not be. -//! Please check the exact struct type definition here. For example the definition for CheckNonce is -//! `CheckNonce(#[codec(compact)] pub T::Index)`. We can see that the `#[codec(compact)` -//! attribute tells us that the `u32` value needs to be compact encoded. -//! -//! Because the `pallet_asset_tx_payment::ChargeAssetTxPayment` struct requires us to pass the -//! struct of our `Runtime` as a generic argument, we decide to just recreate the struct here. This prohibits us -//! from pulling in tons of unneeded dependencies. This is a pattern that you might see often, -//! especially because substrate crates and their types are quite big, clunky and entangled sometimes. -//! -//! With all these types collected, we can create two structs: `StatemintExtraParams` and `StatemintAdditionalParams`. -//! Then we combine them into a `StatemintExtrinsicParams` struct for which we implement the [crate::config::ExtrinsicParams] trait, see below. -//! Now we have all the parts we need to create our config `StatemintConfig` and implment the [crate::Config] trait on it. -//! Note that StatemintConfig is an empty enum, an _uninhabited type_ that is never means to be instantiated -//! but just gives type information to various interfaces of _subxt_. +//! which has an associated type `AdditionalSigned` that also implements [codec::Encode]. Let's look at the underlying types +//! for each tuple element. All zero-sized types have been replaced by `()` for simplicity. +//! +//! | tuple element | struct type | `AdditionalSigned` type | +//! | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | +//! | [`frame_system::CheckNonZeroSender`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonZeroSender.html) | () | () | +//! | [`frame_system::CheckSpecVersion`](https://docs.rs/frame-system/latest/frame_system/struct.CheckSpecVersion.html) | () | [u32] | +//! | [`frame_system::CheckTxVersion`](https://docs.rs/frame-system/latest/frame_system/struct.CheckTxVersion.html) | () | [u32] | +//! | [`frame_system::CheckGenesis`](https://docs.rs/frame-system/latest/frame_system/struct.CheckGenesis.html) | () | `Config::Hash` = [sp_core::H256] | +//! | [`frame_system::CheckMortality`](https://docs.rs/frame-system/latest/frame_system/struct.CheckMortality.html) | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | +//! | [`frame_system::CheckNonce`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `Config::Index` = [u32] | () | +//! | [`frame_system::CheckWeight`](https://docs.rs/frame-system/latest/frame_system/struct.CheckWeight.html) | () | () | +//! | [`frame_system::ChargeAssetTxPayment`](https://docs.rs/frame-system/latest/frame_system/struct.ChargeAssetTxPayment.html) | [pallet_asset_tx_payment::ChargeAssetTxPayment](https://docs.rs/pallet-asset-tx-payment/latest/pallet_asset_tx_payment/struct.ChargeAssetTxPayment.html) | () | +//! +//! All types in the `struct type` column make up the "extra" data that we're expected to provide. All types in the +//! `AdditionalSigned` column make up the "additional" data that we're expected to provide. The goal of an +//! [`crate::config::ExtrinsicParams`] then is to provide the appropriate data for these via [`crate::config::ExtrinsicParams::encode_extra_to()`] +//! and [`crate::config::ExtrinsicParams::encode_additional_to()`] respectively. If it needs additional parameters from +//! the user to provide this data, it can obtain it via [`crate::config::ExtrinsicParams::OtherParams`]. +//! +//! Given the above information, here is a fairly naive approach to implementing config for Statemint, including the +//! [`crate::config::ExtrinsicParams`] trait, in a compatible way: //! //! ```rust,ignore -#![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_verbose.rs")] +#![doc = include_str ! ("../../../examples/setup_config_custom.rs")] //! ``` //! -//! ## 2. Simplifying the config -//! -//! Now you should be able to create a config for a parachain from scratch and understand the details of its construction. -//! However this is quite a tedious process, so subxt provides some sane defaults that can make your life easier. -//! First, let's ditch the dependencies to [sp_core] and [sp_runtime]. -//! We should not be forced to utilize these traits whenever we create a config for a chain. -//! That is why subxt provides some types that can function as drop in replacements for some types in [sp_core] and [sp_runtime]. -//! You can use: -//! - [crate::config::extrinsic_params::Era] instead of [sp_runtime::generic::Era] -//! - [crate::utils::AccountId32] instead of [sp_core::crypto::AccountId32] -//! - [crate::utils::MultiAddress] instead of [sp_runtime::MultiAddress] -//! - [crate::utils::H160], [crate::utils::H256] and [crate::utils::H512] instead of [sp_core::H256], [sp_core::H160] and [sp_core::H512] -//! - [crate::utils::MultiAddress] instead of [sp_runtime::MultiAddress] -//! - [crate::config::substrate::Era] instead of [sp_runtime::generic::Era] -//! - [crate::config::substrate::SubstrateHeader] instead of [sp_runtime::generic::Header] -//! - [crate::config::substrate::AssetTip] and [crate::config::polkadot::PlainTip] instead of [pallet_transaction_payment::ChargeTransactionPayment](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/struct.ChargeTransactionPayment.html) -//! - [crate::config::substrate::BlakeTwo256] instead of [sp_core::Blake2Hasher] or [sp_runtime::traits::BlakeTwo256] -//! - [crate::config::substrate::DigestItem] and [crate::config::substrate::Digest] instead of [sp_runtime::generic::Digest] and [sp_runtime::generic::DigestItem] -//! - [crate::config::substrate::ConsensusEngineId] instead of [sp_runtime::ConsensusEngineId] -//! -//! With these optimizations, our config can look like this: -//! -//! ```rust,ignore -#![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_with_subxt_types.rs")] -//! ``` -//! -//! ## 3. Use the [`PolkadotConfig`](crate::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig) to compose a Config +//! ## Using [`PolkadotConfig`](crate::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig) values to compose a Config //! //! Because most substrate based chains share a great deal of types, _subxt_ already provides two configs: -//! - [`SubstrateConfig`](crate::SubstrateConfig) configured for the default [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) -//! - [`PolkadotConfig`](crate::PolkadotConfig) configured for the [polkadot node implementation](https://github.com/paritytech/polkadot) +//! - [`SubstrateConfig`](crate::SubstrateConfig) configured for the default +//! [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) +//! - [`PolkadotConfig`](crate::PolkadotConfig) configured for the +//! [polkadot node implementation](https://github.com/paritytech/polkadot) //! -//! Even those two just differ in the type of the `Tip` and `MultiAddress`. -//! Statemint (Polkadot Asset Hub) seems to match the Polkadot config in almost all points, except for the `ExtrinsicParams`. -//! Here the tips follow the same structure as for the default substrate node. -//! We can now simply build the config for Statemint from the building blocks provided -//! by [`PolkadotConfig`](crate::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig) as shown below. +//! These two configs are quite similar, and only differ slightly in the `MultiAddress` type, and in terms of the type of `Tip` provided +//! as part of the `ExtrinsicParams`. +//! +//! Looking at the Statemint config, we can see that it is very similar to these. It ultimately uses the same signed extensions that +//! Substrate uses, and otherwise uses the same types as Polkadot. So, we can create a config which just reuses these existing types: //! //! ```rust,ignore -#![doc = include_str ! ("../../../../examples/parachain-example/src/statemint_config_composed.rs")] +//! use subxt::{Config, PolkadotConfig, SubstrateConfig}; +//! +//! pub enum StatemintConfig {} +//! +//! impl Config for StatemintConfig { +//! type Index = ::Index; +//! type Hash = ::Hash; +//! type AccountId = ::AccountId; +//! type Address = ::Address; +//! type Signature = ::Signature; +//! type Hasher = ::Hasher; +//! type Header = ::Header; +//! // this is the only difference to the PolkadotConfig: +//! type ExtrinsicParams = ::ExtrinsicParams; +//! } //! ``` +//! +//! This saves us a bunch of effort over creating our own `ExtrinsicParams` and so on, but is only applicable when such types are the +//! same between the chain you're interested in interacting with, and either Substrate or Polkadot. From 887e83d1177dbdad15c3673c67308d71cd4be775 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 19 Jul 2023 10:14:04 +0100 Subject: [PATCH 20/28] another pass over docs and link to exampels from guide --- subxt/src/book/mod.rs | 9 +++++++ subxt/src/book/setup/config.rs | 49 +++++++++++++++++----------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/subxt/src/book/mod.rs b/subxt/src/book/mod.rs index a729532ab7..95091c04c2 100644 --- a/subxt/src/book/mod.rs +++ b/subxt/src/book/mod.rs @@ -93,5 +93,14 @@ //! - [Runtime APIs](usage::runtime_apis): Subxt can make calls into pallet runtime APIs to retrieve //! data. //! +//! ## Examples +//! +//! Some complete, self contained examples which are not a part of this guide: +//! +//! - [`parachain-example`](https://github.com/paritytech/subxt/tree/master/examples/parachain-example) is an example +//! which uses Zombienet to spawn a parachain locally, and then connects to it using Subxt. +//! - [`wasm-example`](https://github.com/paritytech/subxt/tree/master/examples/wasm-example) is an example of writing +//! a Rust app that contains a Yew based UI, uses Subxt to interact with a chain, and compiles to WASM in order to +//! run entirely in the browser. pub mod setup; pub mod usage; diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index 85f93e584f..4688897229 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -12,8 +12,8 @@ //! Some chains may use config that is not compatible with our [`PolkadotConfig`](crate::config::PolkadotConfig) or //! [`SubstrateConfig`](crate::config::SubstrateConfig). //! -//! We now walk through how a subxt [`crate::config::Config`] can be created for a parachain, using the -//! ["Statemint"](https://parachains.info/details/statemint) parachain, also known as "Asset Hub" as an example. It +//! We now walk through creating a [`crate::config::Config`] for a parachain, using the +//! ["Statemint"](https://parachains.info/details/statemint) parachain, also known as "Asset Hub", as an example. It //! is currently (as of 2023-06-26) deployed on Polkadot and [Kusama (as "Statemine")](https://parachains.info/details/statemine). //! //! To construct a config, we need to investigate which types Statemint uses as `AccountId`, `Hasher`, etc. @@ -24,15 +24,15 @@ //! ## Creating the `Config` from scratch //! //! Creating the config from scratch is the most arduous approach but also the most flexible, so first we'll walk through -//! how to do this, and then we'll show how to simplify the process, which can be achieved in most cases. +//! how to do this, and then we'll show how to simplify the process where possible. //! //! ### AccountId, Index, Hash, Hasher and Header //! //! For these config types, we need to find out where the parachain runtime implements the `frame_system::Config` trait. //! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. -//! For Statemint we find it [here](https://github.com/paritytech/cumulus/tree/master/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179). -//! The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) -//! should also be the ones we want to use for implementing [crate::Config]. In the Case of Statemint (Asset Hub) they are: +//! For Statemint it looks like [this](https://github.com/paritytech/cumulus/blob/e2b7ad2061824f490c08df27a922c64f50accd6b/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179) +//! at the time of writing. The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) +//! correspond to the ones we want to use for implementing [crate::Config]. In the Case of Statemint (Asset Hub) they are: //! //! - AccountId: [`sp_core::crypto::AccountId32`] //! - Index: [`u32`] @@ -56,8 +56,9 @@ //! In this macro, we need to specify the type of an `UncheckedExtrinsic`. Most of the time, the `UncheckedExtrinsic` will be of the type //! [sp_runtime::generic::UncheckedExtrinsic](sp_runtime::generic::UncheckedExtrinsic). //! The generic parameters `Address` and `Signature` specified when declaring the `UncheckedExtrinsic` type -//! are the types for `Address` and `Signature` we should use when implementing the [crate::Config] trait. -//! In case of Statemint (Polkadot Asset Hub) we see the following types being used in `UncheckedExtrinsic`: +//! are the types for `Address` and `Signature` we should use when implementing the [crate::Config] trait. This information can +//! also be obtained from the metadata (see [`frame_metadata::v15::ExtrinsicMetadata`]). In case of Statemint (Polkadot Asset Hub) +//! we see the following types being used in `UncheckedExtrinsic`: //! //! - Address: [sp_runtime::MultiAddress](sp_runtime::MultiAddress) //! - Signature: [sp_runtime::MultiSignature] @@ -70,9 +71,10 @@ //! //! ### ExtrinsicParams //! -//! Parachains each have a set of "signed extensions" configured. Signed extensions provide a means to extend how transactions +//! Chains each have a set of "signed extensions" configured. Signed extensions provide a means to extend how transactions //! work. Each signed extension can potentially encode some "extra" data which is sent along with a transaction, as well as some -//! "additional" data which is included in the transaction signer payload, but not transmitted along with the transaction. +//! "additional" data which is included in the transaction signer payload, but not transmitted along with the transaction. On +//! a node, signed extensions can then perform additional checks on the submitted transactions to ensure their validity. //! //! The `ExtrinsicParams` config type expects to be given an implementation of the [`crate::config::ExtrinsicParams`] trait. //! Implementations of the [`crate::config::ExtrinsicParams`] trait are handed some parameters from Subxt itself, and can @@ -116,9 +118,10 @@ //! //! All types in the `struct type` column make up the "extra" data that we're expected to provide. All types in the //! `AdditionalSigned` column make up the "additional" data that we're expected to provide. The goal of an -//! [`crate::config::ExtrinsicParams`] then is to provide the appropriate data for these via [`crate::config::ExtrinsicParams::encode_extra_to()`] -//! and [`crate::config::ExtrinsicParams::encode_additional_to()`] respectively. If it needs additional parameters from -//! the user to provide this data, it can obtain it via [`crate::config::ExtrinsicParams::OtherParams`]. +//! [`crate::config::ExtrinsicParams`] impl then is to provide the appropriate (SCALE encoded) data for these via +//! [`crate::config::ExtrinsicParams::encode_extra_to()`] and [`crate::config::ExtrinsicParams::encode_additional_to()`] +//! respectively. If the [`crate::config::ExtrinsicParams`] impl needs additional data to be able to do this, it can use +//! the [`crate::config::ExtrinsicParams::OtherParams`] associated type to obtain it from the user. //! //! Given the above information, here is a fairly naive approach to implementing config for Statemint, including the //! [`crate::config::ExtrinsicParams`] trait, in a compatible way: @@ -129,17 +132,14 @@ //! //! ## Using [`PolkadotConfig`](crate::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig) values to compose a Config //! -//! Because most substrate based chains share a great deal of types, _subxt_ already provides two configs: -//! - [`SubstrateConfig`](crate::SubstrateConfig) configured for the default -//! [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) -//! - [`PolkadotConfig`](crate::PolkadotConfig) configured for the -//! [polkadot node implementation](https://github.com/paritytech/polkadot) +//! Subxt already provides [`PolkadotConfig`](crate::config::PolkadotConfig) and [`SubstrateConfig`](crate::SubstrateConfig). These +//! two configs are actually very similar, and only differ slightly in the `MultiAddress` type, and in terms of the type of `Tip` provided +//! as part of the `ExtrinsicParams`. Many chains share a lot of the same types as these, and so often times you can just reuse parts +//! of these implementations. //! -//! These two configs are quite similar, and only differ slightly in the `MultiAddress` type, and in terms of the type of `Tip` provided -//! as part of the `ExtrinsicParams`. -//! -//! Looking at the Statemint config, we can see that it is very similar to these. It ultimately uses the same signed extensions that -//! Substrate uses, and otherwise uses the same types as Polkadot. So, we can create a config which just reuses these existing types: +//! From looking at the types needed for the Statemint config above, we can see that it is indeed very similar to these. It ultimately +//! uses the same signed extensions that Substrate uses, and otherwise uses the same types as Polkadot. So, we can create a config which +//! just reuses these existing types: //! //! ```rust,ignore //! use subxt::{Config, PolkadotConfig, SubstrateConfig}; @@ -159,5 +159,4 @@ //! } //! ``` //! -//! This saves us a bunch of effort over creating our own `ExtrinsicParams` and so on, but is only applicable when such types are the -//! same between the chain you're interested in interacting with, and either Substrate or Polkadot. +//! When the types are very similar, building a custom config like this is much simpler than implementing one from scratch. From eab60325d4fb444f355639a7c984ee34f3b13e11 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Wed, 19 Jul 2023 11:44:45 +0200 Subject: [PATCH 21/28] nit: adjust comment to numbers --- examples/parachain-example/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 38ad9dde77..e0718106fc 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -44,7 +44,7 @@ async fn run() -> Result<(), Box> { const COLLECTION_ID: u32 = 12; const NTF_ID: u32 = 234; - // create a collection with id `42` + // create a collection with id `12` let collection_creation_tx = statemint::tx() .uniques() .create(COLLECTION_ID, alice.clone()); @@ -60,7 +60,7 @@ async fn run() -> Result<(), Box> { .await?; println!("Collection created."); - // create an nft in that collection with id `420` + // create an nft in that collection with id `234` let nft_creation_tx = statemint::tx() .uniques() .mint(COLLECTION_ID, NTF_ID, alice.clone()); From 375cdc91a0bbf40855899ec3d47bcb17a815d692 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 19 Jul 2023 10:49:59 +0100 Subject: [PATCH 22/28] teeny README fix for parachain-example --- examples/parachain-example/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/parachain-example/README.md b/examples/parachain-example/README.md index 988e678bda..078cb8e15e 100644 --- a/examples/parachain-example/README.md +++ b/examples/parachain-example/README.md @@ -21,7 +21,6 @@ and install it in your path: ```txt git clone https://github.com/paritytech/polkadot.git cd polkadot -cargo build --release cargo install --path . ``` @@ -34,8 +33,7 @@ Asset Hub nodes. ```txt git clone https://github.com/paritytech/cumulus.git cd cumulus -cargo build --release -cargo install --path . +cargo install --path polkadot-parachain ``` ### 4. Run the parachain locally From 67d412fd45d1b1987bad6477c7a53500477ad0a6 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 19 Jul 2023 17:35:37 +0100 Subject: [PATCH 23/28] fix command in readme --- examples/parachain-example/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/parachain-example/README.md b/examples/parachain-example/README.md index 078cb8e15e..b11622cd1c 100644 --- a/examples/parachain-example/README.md +++ b/examples/parachain-example/README.md @@ -59,7 +59,7 @@ The parachain is only registered after the first epoch. So after the previous st interactive and produces blocks. At this point, we can run: ``` -cargo run --bin +cargo run --bin parachain-example ``` To run our example code. From 77eeda65fa2867f01eeb613e07beaea060049a82 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 19 Jul 2023 17:49:28 +0100 Subject: [PATCH 24/28] add CI for examples and fix parachain-example bug I left in --- .github/workflows/rust.yml | 34 +- Cargo.toml | 3 +- examples/parachain-example/Cargo.lock | 863 +++++++++++++++++++- examples/parachain-example/src/main.rs | 9 +- examples/wasm-example/Cargo.lock | 1040 ++++++++++++++++++++++-- 5 files changed, 1855 insertions(+), 94 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d5d8d62982..ceaaa24a88 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -24,7 +24,7 @@ env: WASM_BINDGEN_TEST_TIMEOUT: 60 jobs: - build: + check: name: Cargo check runs-on: ubuntu-latest steps: @@ -83,6 +83,34 @@ jobs: - name: Cargo hack; check each feature/crate on its own run: cargo hack --exclude subxt --exclude subxt-signer --exclude subxt-lightclient --exclude-all-features --each-feature check --workspace + # Check examples, which aren't a part of the workspace and so are otherwise missed: + - name: Cargo check examples + run: | + cargo check --manifest-path examples/parachain-example/Cargo.toml + + wasm_check: + name: Cargo check (WASM) + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Install Rust stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + target: wasm32-unknown-unknown + override: true + + - name: Rust Cache + uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + + # Check WASM examples, which aren't a part of the workspace and so are otherwise missed: + - name: Cargo check WASM examples + run: | + cargo check --manifest-path examples/wasm-example/Cargo.toml + fmt: name: Cargo fmt runs-on: ubuntu-latest @@ -141,7 +169,7 @@ jobs: command: test args: --doc - nonwasm_tests: + tests: name: "Test non-wasm" runs-on: ubuntu-latest-16-cores steps: @@ -175,7 +203,7 @@ jobs: command: nextest args: run --workspace - nonwasm_light_client_tests: + light_client_tests: name: "Test Light Client" runs-on: ubuntu-latest-16-cores timeout-minutes: 25 diff --git a/Cargo.toml b/Cargo.toml index ab148fe22d..7ad456e3e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,8 @@ exclude = [ "testing/wasm-rpc-tests", "testing/wasm-lightclient-tests", "signer/wasm-tests", - "examples/wasm-example" + "examples/wasm-example", + "examples/parachain-example" ] resolver = "2" diff --git a/examples/parachain-example/Cargo.lock b/examples/parachain-example/Cargo.lock index c023a33ca5..06f55b7481 100644 --- a/examples/parachain-example/Cargo.lock +++ b/examples/parachain-example/Cargo.lock @@ -27,6 +27,41 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "ahash" version = "0.7.6" @@ -101,6 +136,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.5.2" @@ -113,6 +157,63 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.20", + "slab", + "socket2", + "waker-fn", +] + [[package]] name = "async-lock" version = "2.7.0" @@ -122,6 +223,42 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-net" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" +dependencies = [ + "async-io", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +dependencies = [ + "async-io", + "async-lock", + "autocfg", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 0.37.20", + "signal-hook", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + [[package]] name = "async-trait" version = "0.1.68" @@ -133,6 +270,18 @@ dependencies = [ "syn 2.0.25", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" + [[package]] name = "autocfg" version = "1.1.0" @@ -234,6 +383,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + [[package]] name = "blake2b_simd" version = "1.0.1" @@ -242,7 +401,7 @@ checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", "arrayvec 0.7.4", - "constant_time_eq", + "constant_time_eq 0.2.6", ] [[package]] @@ -284,6 +443,21 @@ dependencies = [ "byte-tools", ] +[[package]] +name = "blocking" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "log", +] + [[package]] name = "bounded-collections" version = "0.1.8" @@ -302,6 +476,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -344,6 +527,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + [[package]] name = "chrono" version = "0.4.26" @@ -356,12 +564,42 @@ dependencies = [ "winapi", ] +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "constant_time_eq" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.3" @@ -414,6 +652,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -450,6 +707,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "2.1.3" @@ -476,6 +742,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" +dependencies = [ + "cfg-if", + "fiat-crypto", + "packed_simd_2", + "platforms", + "subtle", + "zeroize", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -576,8 +856,10 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version", "syn 1.0.109", ] @@ -610,6 +892,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -729,6 +1017,21 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -761,6 +1064,17 @@ name = "frame-metadata" version = "15.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" dependencies = [ "cfg-if", "parity-scale-codec", @@ -823,6 +1137,21 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.28" @@ -911,6 +1240,16 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug 0.3.0", + "polyval", +] + [[package]] name = "gimli" version = "0.27.3" @@ -979,6 +1318,9 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "serde", +] [[package]] name = "heck" @@ -1210,6 +1552,21 @@ dependencies = [ "hashbrown 0.14.0", ] +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "integer-sqrt" version = "0.1.5" @@ -1219,6 +1576,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "intx" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f38a50a899dc47a6d0ed5508e7f601a2e34c3a85303514b5d137f3c10a0c75" + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -1230,6 +1593,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.6" @@ -1355,6 +1727,18 @@ version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + [[package]] name = "libsecp256k1" version = "0.7.1" @@ -1431,6 +1815,12 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" + [[package]] name = "mach" version = "0.3.2" @@ -1506,6 +1896,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -1526,20 +1922,75 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "nohash-hasher" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.4", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] [[package]] -name = "num-format" -version = "0.4.4" +name = "num-rational" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ - "arrayvec 0.7.4", - "itoa", + "autocfg", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] @@ -1597,6 +2048,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "packed_simd_2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" +dependencies = [ + "cfg-if", + "libm 0.1.4", +] + [[package]] name = "parachain-example" version = "0.1.0" @@ -1639,6 +2100,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1733,6 +2200,51 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "platforms" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1788,9 +2300,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -1806,9 +2318,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.29" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" dependencies = [ "proc-macro2", ] @@ -1972,7 +2484,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -1996,6 +2508,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.14" @@ -2063,6 +2584,17 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +[[package]] +name = "ruzstd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" +dependencies = [ + "byteorder", + "thiserror-core", + "twox-hash", +] + [[package]] name = "ryu" version = "1.0.13" @@ -2138,9 +2670,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad560913365790f17cbf12479491169f01b9d46d29cfc7422bf8c64bdc61b731" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" dependencies = [ "bitvec", "cfg-if", @@ -2152,9 +2684,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19df9bd9ace6cc2fe19387c96ce677e823e07d017ceed253e7bb3d1d1bd9c73b" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2171,7 +2703,7 @@ dependencies = [ "base58", "blake2", "either", - "frame-metadata", + "frame-metadata 15.1.0", "parity-scale-codec", "scale-bits", "scale-decode", @@ -2259,7 +2791,16 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.1", ] [[package]] @@ -2271,6 +2812,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -2303,6 +2853,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "serde" version = "1.0.171" @@ -2411,12 +2967,37 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "slab" version = "0.4.8" @@ -2432,6 +3013,120 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "smol" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smoldot" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cce5e2881b30bad7ef89f383a816ad0b22c45915911f28499026de4a76d20ee" +dependencies = [ + "arrayvec 0.7.4", + "async-lock", + "atomic", + "base64 0.21.2", + "bip39", + "blake2-rfc", + "bs58 0.5.0", + "crossbeam-queue", + "derive_more", + "ed25519-zebra", + "either", + "event-listener", + "fnv", + "futures-channel", + "futures-util", + "hashbrown 0.14.0", + "hex", + "hmac 0.12.1", + "itertools", + "libsecp256k1", + "merlin 3.0.0", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "pbkdf2 0.12.2", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", + "ruzstd", + "schnorrkel 0.10.2", + "serde", + "serde_json", + "sha2 0.10.7", + "siphasher", + "slab", + "smallvec", + "smol", + "snow", + "soketto", + "tiny-keccak", + "twox-hash", + "wasmi", +] + +[[package]] +name = "smoldot-light" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2f7b4687b83ff244ef6137735ed5716ad37dcdf3ee16c4eb1a32fb9808fa47" +dependencies = [ + "async-lock", + "blake2-rfc", + "derive_more", + "either", + "event-listener", + "fnv", + "futures-channel", + "futures-util", + "hashbrown 0.14.0", + "hex", + "itertools", + "log", + "lru", + "parking_lot", + "rand 0.8.5", + "serde", + "serde_json", + "siphasher", + "slab", + "smol", + "smoldot", +] + +[[package]] +name = "snow" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.0.0-rc.1", + "rand_core 0.6.4", + "rustc_version", + "sha2 0.10.7", + "subtle", +] + [[package]] name = "socket2" version = "0.4.9" @@ -2496,7 +3191,7 @@ dependencies = [ "bitflags", "blake2", "bounded-collections", - "bs58", + "bs58 0.4.0", "dyn-clonable", "ed25519-zebra", "futures", @@ -2515,7 +3210,7 @@ dependencies = [ "regex", "scale-info", "schnorrkel 0.9.1", - "secp256k1", + "secp256k1 0.24.3", "secrecy", "serde", "sp-core-hashing", @@ -2583,7 +3278,7 @@ dependencies = [ "log", "parity-scale-codec", "rustversion", - "secp256k1", + "secp256k1 0.24.3", "sp-core", "sp-externalities", "sp-keystore", @@ -2790,6 +3485,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "ss58-registry" version = "1.40.0" @@ -2856,7 +3557,7 @@ dependencies = [ "blake2", "derivative", "either", - "frame-metadata", + "frame-metadata 16.0.0", "futures", "hex", "impl-serde", @@ -2873,6 +3574,7 @@ dependencies = [ "sp-core", "sp-core-hashing", "sp-runtime", + "subxt-lightclient", "subxt-macro", "subxt-metadata", "thiserror", @@ -2883,7 +3585,7 @@ dependencies = [ name = "subxt-codegen" version = "0.29.0" dependencies = [ - "frame-metadata", + "frame-metadata 16.0.0", "heck", "hex", "jsonrpsee", @@ -2897,6 +3599,21 @@ dependencies = [ "tokio", ] +[[package]] +name = "subxt-lightclient" +version = "0.29.0" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + [[package]] name = "subxt-macro" version = "0.29.0" @@ -2911,7 +3628,7 @@ dependencies = [ name = "subxt-metadata" version = "0.29.0" dependencies = [ - "frame-metadata", + "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", "sp-core-hashing", @@ -2929,6 +3646,7 @@ dependencies = [ "pbkdf2 0.12.2", "regex", "schnorrkel 0.10.2", + "secp256k1 0.27.0", "secrecy", "sha2 0.10.7", "sp-core-hashing", @@ -2980,6 +3698,26 @@ dependencies = [ "thiserror-impl", ] +[[package]] +name = "thiserror-core" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" +dependencies = [ + "thiserror-core-impl", +] + +[[package]] +name = "thiserror-core-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "thiserror-impl" version = "1.0.40" @@ -3020,6 +3758,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3075,6 +3822,17 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.8" @@ -3274,6 +4032,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -3303,6 +4071,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "want" version = "0.3.1" @@ -3378,6 +4152,38 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasmi" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51fb5c61993e71158abf5bb863df2674ca3ec39ed6471c64f07aeaf751d67b4" +dependencies = [ + "intx", + "smallvec", + "spin 0.9.8", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "401c1f35e413fac1846d4843745589d9ec678977ab35a384db8ae7830525d468" + +[[package]] +name = "wasmi_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624e6333e861ef49095d2d678b76ebf30b06bf37effca845be7e5b87c90071b7" +dependencies = [ + "downcast-rs", + "libm 0.2.7", + "num-traits", + "paste", +] + [[package]] name = "wasmparser" version = "0.102.0" @@ -3388,6 +4194,15 @@ dependencies = [ "url", ] +[[package]] +name = "wasmparser-nostd" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +dependencies = [ + "indexmap-nostd", +] + [[package]] name = "wasmtime" version = "8.0.1" diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index e0718106fc..7434c9c6e9 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -1,16 +1,13 @@ -#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] -pub mod statemint {} - -use parachain_example::statemint; -use parachain_example::statemint_config_composed::StatemintConfig; use subxt::{ Config, PolkadotConfig, SubstrateConfig, utils::{AccountId32, MultiAddress}, OnlineClient, }; - use subxt_signer::sr25519::dev::{self}; +#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] +pub mod statemint {} + /// Custom config that works with Statemint: pub enum StatemintConfig {} diff --git a/examples/wasm-example/Cargo.lock b/examples/wasm-example/Cargo.lock index 795141f57c..ee32aa6735 100644 --- a/examples/wasm-example/Cargo.lock +++ b/examples/wasm-example/Cargo.lock @@ -2,6 +2,67 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -20,6 +81,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.7.2" @@ -43,15 +113,36 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base58" version = "0.2.0" @@ -88,6 +179,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bip39" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +dependencies = [ + "bitcoin_hashes", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + [[package]] name = "bitflags" version = "1.3.2" @@ -115,6 +221,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + [[package]] name = "blake2b_simd" version = "1.0.1" @@ -122,8 +238,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec", - "constant_time_eq", + "arrayvec 0.7.2", + "constant_time_eq 0.2.5", ] [[package]] @@ -150,6 +266,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -186,6 +311,40 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -196,12 +355,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "constant_time_eq" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.3" @@ -227,6 +398,25 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -243,6 +433,65 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" +dependencies = [ + "cfg-if", + "fiat-crypto", + "packed_simd_2", + "platforms", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + [[package]] name = "darling" version = "0.14.4" @@ -288,7 +537,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] @@ -310,7 +559,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core 0.20.1", "quote", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] @@ -330,8 +579,10 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ + "convert_case", "proc-macro2", "quote", + "rustc_version", "syn 1.0.109", ] @@ -355,6 +606,26 @@ dependencies = [ "subtle", ] +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "either" version = "1.8.1" @@ -367,6 +638,12 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -399,6 +676,17 @@ name = "frame-metadata" version = "15.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" dependencies = [ "cfg-if", "parity-scale-codec", @@ -468,7 +756,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] @@ -490,7 +778,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" dependencies = [ "gloo-timers", - "send_wrapper", + "send_wrapper 0.4.0", ] [[package]] @@ -534,6 +822,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "gloo" version = "0.8.0" @@ -725,6 +1029,18 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "serde", +] [[package]] name = "heck" @@ -747,6 +1063,36 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + [[package]] name = "http" version = "0.2.9" @@ -872,7 +1218,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "intx" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f38a50a899dc47a6d0ed5508e7f601a2e34c3a85303514b5d137f3c10a0c75" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", ] [[package]] @@ -995,35 +1374,189 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.144" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libm" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] [[package]] -name = "log" -version = "0.4.17" +name = "num-integer" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ - "cfg-if", + "autocfg", + "num-traits", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "num-rational" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] [[package]] -name = "mio" -version = "0.8.6" +name = "num-traits" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.45.0", + "autocfg", ] [[package]] @@ -1036,6 +1569,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -1054,13 +1596,23 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "packed_simd_2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" +dependencies = [ + "cfg-if", + "libm 0.1.4", +] + [[package]] name = "parity-scale-codec" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ddb756ca205bd108aee3c62c6d3c994e1df84a59b9d6d4a5ea42ee1fd5a9a28" dependencies = [ - "arrayvec", + "arrayvec 0.7.2", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", @@ -1080,6 +1632,21 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -1103,7 +1670,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] @@ -1129,6 +1696,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "platforms" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1194,9 +1790,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -1220,9 +1816,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" dependencies = [ "proc-macro2", ] @@ -1241,7 +1837,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -1251,9 +1847,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + [[package]] name = "rand_core" version = "0.6.4" @@ -1272,12 +1874,18 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1290,6 +1898,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustls" version = "0.20.8" @@ -1329,6 +1946,17 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +[[package]] +name = "ruzstd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" +dependencies = [ + "byteorder", + "thiserror-core", + "twox-hash", +] + [[package]] name = "ryu" version = "1.0.13" @@ -1404,9 +2032,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" dependencies = [ "bitvec", "cfg-if", @@ -1418,9 +2046,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53012eae69e5aa5c14671942a5dd47de59d4cdcff8532a6dd0e081faf1119482" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1437,7 +2065,7 @@ dependencies = [ "base58", "blake2", "either", - "frame-metadata", + "frame-metadata 15.1.0", "parity-scale-codec", "scale-bits", "scale-decode", @@ -1457,6 +2085,22 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "schnorrkel" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "844b7645371e6ecdf61ff246ba1958c29e802881a749ae3fb1993675d210d28d" +dependencies = [ + "arrayref", + "arrayvec 0.7.2", + "curve25519-dalek-ng", + "merlin", + "rand_core 0.6.4", + "sha2 0.9.9", + "subtle-ng", + "zeroize", +] + [[package]] name = "sct" version = "0.7.0" @@ -1490,17 +2134,29 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + [[package]] name = "send_wrapper" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" -version = "1.0.164" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" dependencies = [ "serde_derive", ] @@ -1518,20 +2174,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] name = "serde_json" -version = "1.0.97" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" dependencies = [ "itoa", "ryu", @@ -1563,6 +2219,19 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.6" @@ -1584,6 +2253,12 @@ dependencies = [ "keccak", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "slab" version = "0.4.8" @@ -1599,6 +2274,98 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "smoldot" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cce5e2881b30bad7ef89f383a816ad0b22c45915911f28499026de4a76d20ee" +dependencies = [ + "arrayvec 0.7.2", + "async-lock", + "atomic", + "base64 0.21.2", + "bip39", + "blake2-rfc", + "bs58", + "crossbeam-queue", + "derive_more", + "ed25519-zebra", + "either", + "event-listener", + "fnv", + "futures-channel", + "futures-util", + "hashbrown 0.14.0", + "hex", + "hmac 0.12.1", + "itertools", + "libsecp256k1", + "merlin", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "pbkdf2", + "rand", + "rand_chacha", + "ruzstd", + "schnorrkel", + "serde", + "serde_json", + "sha2 0.10.6", + "siphasher", + "slab", + "smallvec", + "snow", + "tiny-keccak", + "twox-hash", + "wasmi", +] + +[[package]] +name = "smoldot-light" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2f7b4687b83ff244ef6137735ed5716ad37dcdf3ee16c4eb1a32fb9808fa47" +dependencies = [ + "async-lock", + "blake2-rfc", + "derive_more", + "either", + "event-listener", + "fnv", + "futures-channel", + "futures-util", + "hashbrown 0.14.0", + "hex", + "itertools", + "log", + "lru", + "rand", + "serde", + "serde_json", + "siphasher", + "slab", + "smoldot", +] + +[[package]] +name = "snow" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.0.0-rc.1", + "rand_core 0.6.4", + "rustc_version", + "sha2 0.10.6", + "subtle", +] + [[package]] name = "socket2" version = "0.4.9" @@ -1633,7 +2400,7 @@ dependencies = [ "blake2b_simd", "byteorder", "digest 0.10.7", - "sha2", + "sha2 0.10.6", "sha3", "sp-std", "twox-hash", @@ -1651,6 +2418,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "static_assertions" version = "1.1.0" @@ -1669,6 +2442,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + [[package]] name = "subxt" version = "0.29.0" @@ -1677,7 +2456,7 @@ dependencies = [ "blake2", "derivative", "either", - "frame-metadata", + "frame-metadata 16.0.0", "futures", "getrandom", "hex", @@ -1693,6 +2472,7 @@ dependencies = [ "serde", "serde_json", "sp-core-hashing", + "subxt-lightclient", "subxt-macro", "subxt-metadata", "thiserror", @@ -1703,7 +2483,7 @@ dependencies = [ name = "subxt-codegen" version = "0.29.0" dependencies = [ - "frame-metadata", + "frame-metadata 16.0.0", "heck", "hex", "jsonrpsee", @@ -1712,9 +2492,33 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.17", + "syn 2.0.26", + "thiserror", + "tokio", +] + +[[package]] +name = "subxt-lightclient" +version = "0.29.0" +dependencies = [ + "futures", + "futures-timer", + "futures-util", + "getrandom", + "instant", + "js-sys", + "send_wrapper 0.6.0", + "serde", + "serde_json", + "smoldot", + "smoldot-light", "thiserror", "tokio", + "tokio-stream", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -1724,14 +2528,14 @@ dependencies = [ "darling 0.20.1", "proc-macro-error", "subxt-codegen", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] name = "subxt-metadata" version = "0.29.0" dependencies = [ - "frame-metadata", + "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", "sp-core-hashing", @@ -1751,9 +2555,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.17" +version = "2.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45b6ddbb36c5b969c182aec3c4a0bce7df3fbad4b77114706a49aacc80567388" +checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" dependencies = [ "proc-macro2", "quote", @@ -1775,6 +2579,26 @@ dependencies = [ "thiserror-impl", ] +[[package]] +name = "thiserror-core" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" +dependencies = [ + "thiserror-core-impl", +] + +[[package]] +name = "thiserror-core-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "thiserror-impl" version = "1.0.40" @@ -1783,16 +2607,41 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", ] +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.28.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -1811,7 +2660,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] @@ -1894,7 +2743,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", ] [[package]] @@ -1948,6 +2797,16 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +[[package]] +name = "universal-hash" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -1997,7 +2856,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", "wasm-bindgen-shared", ] @@ -2031,7 +2890,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.17", + "syn 2.0.26", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2053,6 +2912,47 @@ dependencies = [ "yew", ] +[[package]] +name = "wasmi" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51fb5c61993e71158abf5bb863df2674ca3ec39ed6471c64f07aeaf751d67b4" +dependencies = [ + "intx", + "smallvec", + "spin 0.9.8", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "401c1f35e413fac1846d4843745589d9ec678977ab35a384db8ae7830525d468" + +[[package]] +name = "wasmi_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624e6333e861ef49095d2d678b76ebf30b06bf37effca845be7e5b87c90071b7" +dependencies = [ + "downcast-rs", + "libm 0.2.7", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +dependencies = [ + "indexmap-nostd", +] + [[package]] name = "web-sys" version = "0.3.63" @@ -2314,3 +3214,23 @@ dependencies = [ "quote", "syn 1.0.109", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] From 9239b0fe81e3d9ea8f4956a7f1907a860a6ff515 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Thu, 20 Jul 2023 14:36:16 +0200 Subject: [PATCH 25/28] add target arch --- subxt/src/client/online_client.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subxt/src/client/online_client.rs b/subxt/src/client/online_client.rs index db242de3bf..15b4f39bd6 100644 --- a/subxt/src/client/online_client.rs +++ b/subxt/src/client/online_client.rs @@ -468,7 +468,7 @@ mod jsonrpsee_helpers { } // helpers for a jsonrpsee specific OnlineClient. -#[cfg(all(feature = "jsonrpsee", feature = "web"))] +#[cfg(all(feature = "jsonrpsee", feature = "web", target_arch = "wasm32"))] mod jsonrpsee_helpers { pub use jsonrpsee::{ client_transport::web, @@ -480,7 +480,7 @@ mod jsonrpsee_helpers { /// Build web RPC client from URL pub async fn client(url: &str) -> Result { - let (sender, receiver) = web::connect(url).await.unwrap(); + let (sender, receiver) = web::connect(url).await.map_err(|e| Error::Transport(e.into()))?; Ok(ClientBuilder::default() .max_notifs_per_subscription(4096) .build_with_wasm(sender, receiver)) From 3a42e652d3093f49d3cb07c234a5a25eb8129236 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Thu, 20 Jul 2023 14:38:17 +0200 Subject: [PATCH 26/28] cargo fmt --- subxt/src/client/online_client.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subxt/src/client/online_client.rs b/subxt/src/client/online_client.rs index 15b4f39bd6..907dd5bc25 100644 --- a/subxt/src/client/online_client.rs +++ b/subxt/src/client/online_client.rs @@ -480,7 +480,9 @@ mod jsonrpsee_helpers { /// Build web RPC client from URL pub async fn client(url: &str) -> Result { - let (sender, receiver) = web::connect(url).await.map_err(|e| Error::Transport(e.into()))?; + let (sender, receiver) = web::connect(url) + .await + .map_err(|e| Error::Transport(e.into()))?; Ok(ClientBuilder::default() .max_notifs_per_subscription(4096) .build_with_wasm(sender, receiver)) From 750002d3fcaeb1eb39f058fe7d76e288d92c37b5 Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Thu, 20 Jul 2023 15:23:38 +0200 Subject: [PATCH 27/28] make CI not fail --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ceaaa24a88..dcf78a48b2 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -109,7 +109,7 @@ jobs: # Check WASM examples, which aren't a part of the workspace and so are otherwise missed: - name: Cargo check WASM examples run: | - cargo check --manifest-path examples/wasm-example/Cargo.toml + cargo check --manifest-path examples/wasm-example/Cargo.toml --target wasm32-unknown-unknown fmt: name: Cargo fmt From 0d0368ea74b2afa05d5c58029e005b30c91dfa2b Mon Sep 17 00:00:00 2001 From: Tadeo hepperle Date: Fri, 21 Jul 2023 10:35:15 +0200 Subject: [PATCH 28/28] remove index from docs --- examples/parachain-example/src/main.rs | 1 - subxt/examples/setup_config_custom.rs | 7 +++---- subxt/src/book/setup/config.rs | 8 +++----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 7434c9c6e9..9b7537d5df 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -12,7 +12,6 @@ pub mod statemint {} pub enum StatemintConfig {} impl Config for StatemintConfig { - type Index = ::Index; type Hash = ::Hash; type AccountId = ::AccountId; type Address = ::Address; diff --git a/subxt/examples/setup_config_custom.rs b/subxt/examples/setup_config_custom.rs index c2df705694..d5edcc0490 100644 --- a/subxt/examples/setup_config_custom.rs +++ b/subxt/examples/setup_config_custom.rs @@ -7,7 +7,6 @@ use subxt::config::{Config, ExtrinsicParams}; pub enum StatemintConfig {} impl Config for StatemintConfig { - type Index = u32; type Hash = subxt::utils::H256; type AccountId = subxt::utils::AccountId32; type Address = subxt::utils::MultiAddress; @@ -23,7 +22,7 @@ pub struct StatemintExtrinsicParams { additional_params: StatemintAdditionalParams, } -impl ExtrinsicParams for StatemintExtrinsicParams { +impl ExtrinsicParams for StatemintExtrinsicParams { // We need these additional values that aren't otherwise // provided. Calls like api.tx().sign_and_submit_then_watch() // allow the user to provide an instance of these, so it's wise @@ -38,7 +37,7 @@ impl ExtrinsicParams for StatemintExtrinsicParams { fn new( spec_version: u32, tx_version: u32, - nonce: u32, + nonce: u64, genesis_hash: H256, other_params: Self::OtherParams, ) -> Self { @@ -70,7 +69,7 @@ impl ExtrinsicParams for StatemintExtrinsicParams { #[derive(Encode, Debug, Clone, Eq, PartialEq)] pub struct StatemintExtraParams { era: sp_runtime::generic::Era, - nonce: u32, + nonce: u64, charge: ChargeAssetTxPayment, } diff --git a/subxt/src/book/setup/config.rs b/subxt/src/book/setup/config.rs index 4688897229..255130704d 100644 --- a/subxt/src/book/setup/config.rs +++ b/subxt/src/book/setup/config.rs @@ -26,16 +26,15 @@ //! Creating the config from scratch is the most arduous approach but also the most flexible, so first we'll walk through //! how to do this, and then we'll show how to simplify the process where possible. //! -//! ### AccountId, Index, Hash, Hasher and Header +//! ### AccountId, Hash, Hasher and Header //! //! For these config types, we need to find out where the parachain runtime implements the `frame_system::Config` trait. //! Look for a code fragment like `impl frame_system::Config for Runtime { ... }` In the source code. //! For Statemint it looks like [this](https://github.com/paritytech/cumulus/blob/e2b7ad2061824f490c08df27a922c64f50accd6b/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs#L179) -//! at the time of writing. The `AccountId`, `Index`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) +//! at the time of writing. The `AccountId`, `Hash` and `Header` types of the [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html) //! correspond to the ones we want to use for implementing [crate::Config]. In the Case of Statemint (Asset Hub) they are: //! //! - AccountId: [`sp_core::crypto::AccountId32`] -//! - Index: [`u32`] //! - Hash: [`sp_core::H256`] //! - Hasher (type `Hashing` in [frame_system::pallet::Config](https://docs.rs/frame-system/latest/frame_system/pallet/trait.Config.html)): [`sp_runtime::traits::BlakeTwo256`] //! - Header: [`sp_runtime::generic::Header`](sp_runtime::generic::Header) @@ -112,7 +111,7 @@ //! | [`frame_system::CheckTxVersion`](https://docs.rs/frame-system/latest/frame_system/struct.CheckTxVersion.html) | () | [u32] | //! | [`frame_system::CheckGenesis`](https://docs.rs/frame-system/latest/frame_system/struct.CheckGenesis.html) | () | `Config::Hash` = [sp_core::H256] | //! | [`frame_system::CheckMortality`](https://docs.rs/frame-system/latest/frame_system/struct.CheckMortality.html) | [sp_runtime::generic::Era] | `Config::Hash` = [sp_core::H256] | -//! | [`frame_system::CheckNonce`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `Config::Index` = [u32] | () | +//! | [`frame_system::CheckNonce`](https://docs.rs/frame-system/latest/frame_system/struct.CheckNonce.html) | `frame_system::pallet::Config::Index` = u32 | () | //! | [`frame_system::CheckWeight`](https://docs.rs/frame-system/latest/frame_system/struct.CheckWeight.html) | () | () | //! | [`frame_system::ChargeAssetTxPayment`](https://docs.rs/frame-system/latest/frame_system/struct.ChargeAssetTxPayment.html) | [pallet_asset_tx_payment::ChargeAssetTxPayment](https://docs.rs/pallet-asset-tx-payment/latest/pallet_asset_tx_payment/struct.ChargeAssetTxPayment.html) | () | //! @@ -147,7 +146,6 @@ //! pub enum StatemintConfig {} //! //! impl Config for StatemintConfig { -//! type Index = ::Index; //! type Hash = ::Hash; //! type AccountId = ::AccountId; //! type Address = ::Address;