diff --git a/examples/wasm-example/Cargo.lock b/examples/wasm-example/Cargo.lock index cde42f2546..63aea8e290 100644 --- a/examples/wasm-example/Cargo.lock +++ b/examples/wasm-example/Cargo.lock @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "anymap2" @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-lock" @@ -107,13 +107,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -238,8 +238,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec 0.7.2", - "constant_time_eq 0.2.5", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", ] [[package]] @@ -363,9 +363,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "constant_time_eq" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" [[package]] name = "convert_case" @@ -391,9 +391,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -504,12 +504,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core 0.20.1", - "darling_macro 0.20.1", + "darling_core 0.20.3", + "darling_macro 0.20.3", ] [[package]] @@ -528,16 +528,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -553,13 +553,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core 0.20.1", + "darling_core 0.20.3", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -628,9 +628,15 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "event-listener" @@ -664,9 +670,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -756,7 +762,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -811,9 +817,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -840,16 +846,16 @@ checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "gloo" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4bef6b277b3ab073253d4bca60761240cf8d6998f4bd142211957b69a61b20" +checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d" dependencies = [ "gloo-console", "gloo-dialogs", "gloo-events", "gloo-file", "gloo-history", - "gloo-net", + "gloo-net 0.3.0", "gloo-render", "gloo-storage", "gloo-timers", @@ -896,6 +902,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" dependencies = [ + "futures-channel", "gloo-events", "js-sys", "wasm-bindgen", @@ -904,9 +911,9 @@ dependencies = [ [[package]] name = "gloo-history" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd451019e0b7a2b8a7a7b23e74916601abf1135c54664e57ff71dcc26dfcdeb7" +checksum = "ddfd137a4b629e72b8c949ec56c71ea9bd5491cc66358a0a7787e94875feec71" dependencies = [ "gloo-events", "gloo-utils", @@ -938,6 +945,27 @@ dependencies = [ "web-sys", ] +[[package]] +name = "gloo-net" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3000ef231a67d5bfee6b35f2c0f6f5c8d45b3381ef5bbbea603690ec4e539762" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "gloo-render" version = "0.1.1" @@ -977,9 +1005,9 @@ dependencies = [ [[package]] name = "gloo-utils" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" dependencies = [ "js-sys", "serde", @@ -1007,9 +1035,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -1017,7 +1045,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -1050,12 +1078,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -1129,9 +1154,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -1208,7 +1233,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40fc102e70475c320b185cd18c1e48bba2d7210b63970a4d581ef903e4368ef7" dependencies = [ - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -1221,6 +1246,16 @@ dependencies = [ "hashbrown 0.12.3", ] +[[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 = "indexmap-nostd" version = "0.4.0" @@ -1256,15 +1291,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1291,7 +1326,7 @@ dependencies = [ "futures-channel", "futures-timer", "futures-util", - "gloo-net", + "gloo-net 0.2.6", "http", "jsonrpsee-core", "jsonrpsee-types", @@ -1485,14 +1520,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1552,18 +1586,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -1580,9 +1614,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -1608,11 +1642,11 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.5.0" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ddb756ca205bd108aee3c62c6d3c994e1df84a59b9d6d4a5ea42ee1fd5a9a28" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", @@ -1622,9 +1656,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1649,35 +1683,35 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -1816,9 +1850,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -1880,6 +1914,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "route-recognizer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1921,9 +1961,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -1933,18 +1973,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64 0.21.2", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ruzstd" @@ -1959,9 +1999,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scale-bits" @@ -2078,11 +2118,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2092,7 +2132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "844b7645371e6ecdf61ff246ba1958c29e802881a749ae3fb1993675d210d28d" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "curve25519-dalek-ng", "merlin", "rand_core 0.6.4", @@ -2113,9 +2153,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags", "core-foundation", @@ -2126,9 +2166,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2154,18 +2194,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.173" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91f70896d6720bc714a4a57d22fc91f1db634680e65c8efe13323f1fa38d53f" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" dependencies = [ "serde_derive", ] [[package]] name = "serde-wasm-bindgen" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" dependencies = [ "js-sys", "serde", @@ -2174,13 +2214,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.173" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6250dde8342e0232232be9ca3db7aa40aceb5a3e5dd9bddbc00d99a007cde49" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -2234,9 +2274,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -2270,9 +2310,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "smoldot" @@ -2280,7 +2320,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cce5e2881b30bad7ef89f383a816ad0b22c45915911f28499026de4a76d20ee" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "async-lock", "atomic", "base64 0.21.2", @@ -2313,7 +2353,7 @@ dependencies = [ "schnorrkel", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.7", "siphasher", "slab", "smallvec", @@ -2362,7 +2402,7 @@ dependencies = [ "curve25519-dalek 4.0.0-rc.1", "rand_core 0.6.4", "rustc_version", - "sha2 0.10.6", + "sha2 0.10.7", "subtle", ] @@ -2400,7 +2440,7 @@ dependencies = [ "blake2b_simd", "byteorder", "digest 0.10.7", - "sha2 0.10.6", + "sha2 0.10.7", "sha3", "sp-std", "twox-hash", @@ -2450,7 +2490,7 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "subxt" -version = "0.29.0" +version = "0.30.0" dependencies = [ "base58", "blake2", @@ -2481,7 +2521,7 @@ dependencies = [ [[package]] name = "subxt-codegen" -version = "0.29.0" +version = "0.30.0" dependencies = [ "frame-metadata 16.0.0", "heck", @@ -2492,14 +2532,14 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.26", + "syn 2.0.27", "thiserror", "tokio", ] [[package]] name = "subxt-lightclient" -version = "0.29.0" +version = "0.30.0" dependencies = [ "futures", "futures-timer", @@ -2523,17 +2563,17 @@ dependencies = [ [[package]] name = "subxt-macro" -version = "0.29.0" +version = "0.30.0" dependencies = [ - "darling 0.20.1", + "darling 0.20.3", "proc-macro-error", "subxt-codegen", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] name = "subxt-metadata" -version = "0.29.0" +version = "0.30.0" dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", @@ -2555,9 +2595,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ "proc-macro2", "quote", @@ -2572,9 +2612,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] @@ -2601,13 +2641,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -2649,7 +2689,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2660,7 +2700,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -2702,17 +2742,17 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.10" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", "toml_datetime", "winnow", ] @@ -2737,13 +2777,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -2793,9 +2833,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "universal-hash" @@ -2821,11 +2861,10 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -2837,9 +2876,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2847,24 +2886,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -2874,9 +2913,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2884,32 +2923,39 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-example" version = "0.1.0" dependencies = [ + "anyhow", "futures", "hex", + "js-sys", + "serde", + "serde_json", "subxt", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", "yew", + "yew-router", ] [[package]] @@ -2955,9 +3001,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -3004,147 +3050,66 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[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", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 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", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[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" @@ -3153,9 +3118,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" dependencies = [ "memchr", ] @@ -3185,7 +3150,7 @@ dependencies = [ "futures", "gloo", "implicit-clone", - "indexmap", + "indexmap 1.9.3", "js-sys", "prokio", "rustversion", @@ -3215,6 +3180,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "yew-router" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "426ee0486d2572a6c5e39fbdbc48b58d59bb555f3326f54631025266cf04146e" +dependencies = [ + "gloo", + "js-sys", + "route-recognizer", + "serde", + "serde_urlencoded", + "tracing", + "wasm-bindgen", + "web-sys", + "yew", + "yew-router-macro", +] + +[[package]] +name = "yew-router-macro" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b249cdb39e0cddaf0644dedc781854524374664793479fdc01e6a65d6e6ae3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "zeroize" version = "1.6.0" @@ -3232,5 +3226,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] diff --git a/examples/wasm-example/Cargo.toml b/examples/wasm-example/Cargo.toml index a09f1e7451..80d3be6ce7 100644 --- a/examples/wasm-example/Cargo.toml +++ b/examples/wasm-example/Cargo.toml @@ -8,6 +8,13 @@ edition = "2021" [dependencies] futures = "0.3.28" subxt = { path = "../../subxt", default-features = false, features = ["jsonrpsee", "web"], target_arch = "wasm32" } -yew = {version = "0.20.0", features = ["csr"] } +yew = { version = "0.20.0", features = ["csr"] } web-sys = "0.3.63" hex = "0.4.3" +yew-router = "0.17.0" +js-sys = "0.3.63" +wasm-bindgen = "0.2.86" +wasm-bindgen-futures = "0.4.36" +anyhow = "1.0.71" +serde = "1.0.163" +serde_json = "1.0.96" diff --git a/examples/wasm-example/README.md b/examples/wasm-example/README.md index b930f6f09f..de479ee730 100644 --- a/examples/wasm-example/README.md +++ b/examples/wasm-example/README.md @@ -21,3 +21,6 @@ Then, in another terminal, run the app locally with: trunk serve --open ``` +# signing example + +For the signing example, we use the `@polkadot/extension-dapp` NPM package to talk to wallets loaded as browser extensions. In order to sign and submit the transaction using the `polkadot --dev` node we spawned above, you'll need to create a dev account in your wallet of choice. Use the recovery phrase `bottom drive obey lake curtain smoke basket hold race lonely fit walk` and the derivation path `//Alice` to create a dev account that can be used. \ No newline at end of file diff --git a/examples/wasm-example/index.html b/examples/wasm-example/index.html index dbd7370538..60421940dd 100644 --- a/examples/wasm-example/index.html +++ b/examples/wasm-example/index.html @@ -3,6 +3,7 @@ - Yew App + + Subxt Examples Yew App - + \ No newline at end of file diff --git a/examples/wasm-example/index.js b/examples/wasm-example/index.js new file mode 100644 index 0000000000..fe072a8049 --- /dev/null +++ b/examples/wasm-example/index.js @@ -0,0 +1,89 @@ +/** + * The `@polkadot/extension-dapp` package can be dynamically imported. + * Usually it is wise to use a package manager like npm or yarn to install it as a dependency. + * + * The `getPolkadotJsExtensionMod` closure returns the `@polkadot/extension-dapp` module on demand. + */ +let getPolkadotJsExtensionMod = (() => { + let mod = null; + + // initialize `@polkadot/extension-dapp` module on page load + let initPromise = (async () => { + mod = await import( + "https://cdn.jsdelivr.net/npm/@polkadot/extension-dapp@0.46.3/+esm" + ); + })(); + + // return a function that waits for initialization to be finished, in case mod is not initialized yet. + return async () => { + if (mod == null) { + await initPromise; + } + return mod; + }; +})(); + +/** + * Queries wallets from browser extensions like Talisman and the Polkadot.js extension for user accounts. + * + * @returns a json string that contains all the accounts that were found. + */ +async function getAccounts() { + const extensionMod = await getPolkadotJsExtensionMod(); + await extensionMod.web3Enable("Subxt Example App"); + const allAccounts = await extensionMod.web3Accounts(); + const accountObjects = allAccounts.map((account) => ({ + name: account.meta.name, // e.g. "Alice" + source: account.meta.source, // e.g. "talisman", "polkadot-js" + ty: account.type, // e.g. "sr25519" + address: account.address // e.g. "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + })); + console.log(accountObjects); + return JSON.stringify(accountObjects); +} + +/** + * Signs a payload via browser extension + * + * @param payloadAsStr a string representing a JSON object like this: + * let payload = { + * "specVersion": "0x000024d6", + * "transactionVersion": "0x00000018", + * "address": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + * "blockHash": "0xd7aad6185db012b7ffbce710b55234d6c9589170566b925ee50cfa3d7f1e6f8f", + * "blockNumber": "0x00000000", + * "era": "0x0000", + * "genesisHash": "0xd7aad6185db012b7ffbce710b55234d6c9589170566b925ee50cfa3d7f1e6f8f", + * "method": "0x0503001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0b00c465f14670", + * "nonce": "0x00000000", + * "signedExtensions": [ + * "CheckNonZeroSender", + * "CheckSpecVersion", + * "CheckTxVersion", + * "CheckGenesis", + * "CheckMortality", + * "CheckNonce", + * "CheckWeight", + * "ChargeTransactionPayment", + * "PrevalidateAttests" + * ], + * "tip": "0x00000000000000000000000000000000", + * "version": 4 + * }; + * @param source the extension used for signing as a string + * @param address the ss58 encoded address as a string + * @returns {Promise<*>} + */ +async function signPayload(payloadAsStr, source, address) { + let payload = JSON.parse(payloadAsStr); + const extensionMod = await getPolkadotJsExtensionMod(); + const injector = await extensionMod.web3FromSource(source); + const signPayload = injector?.signer?.signPayload; + if (!!signPayload) { + const {signature} = await signPayload(payload); + console.log("signature js:", signature) + return signature; + } else { + throw "The extension's injector does not have a `signPayload` function on its `signer`"; + } +} diff --git a/examples/wasm-example/index.scss b/examples/wasm-example/index.scss index 6fecec8c5e..47dc053001 100644 --- a/examples/wasm-example/index.scss +++ b/examples/wasm-example/index.scss @@ -2,56 +2,101 @@ $primary: #24cc85; $secondary: #1f624a; $dark: #242a35; -*{ - font-family: monospace; - color: $dark; - -} - -html{ - background-color: $dark; - display: flex; - justify-content: center; - height: 100%; -} - -h1{ - font-weight: bolder; - color: $dark; -} - -body{ - width: 800px; - max-width: 100%; - box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; - height: 100%; - margin: 0px; - padding: 16px; - background-color: $primary; -} - - -p{ - white-space: pre-wrap; - border-radius: 8px; - padding: 8px; - box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; - background-color: $dark; - color: white; -} -button{ - font-size: large; - padding: 8px 16px; - font-weight: bold; - background-color: $dark; - border: none; - border-radius: 8px; - color: white; - cursor: pointer; - display: block; - margin-top: 8px; -} - -button:hover{ - background-color: $secondary; -} \ No newline at end of file +* { + font-family: monospace; + color: $dark; +} + +html { + background-color: $dark; + display: flex; + justify-content: center; + height: 100%; +} + +h1 { + font-weight: bolder; + color: $dark; +} + +body { + width: 800px; + max-width: 100%; + box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; + min-height: 100%; + margin: 0px; + padding: 16px; + background-color: $primary; +} + +p { + white-space: pre-wrap; + border-radius: 8px; + padding: 8px; + box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; + background-color: $dark; + color: white; +} + +button { + font-size: large; + padding: 8px 16px; + font-weight: bold; + background-color: $dark; + border: none; + border-radius: 8px; + color: white; + cursor: pointer; + display: block; + margin-top: 8px; +} + +a { + text-decoration: none; +} + +button:hover { + background-color: $secondary; +} + +input { + font-size: large; + background-color: white; + color: $dark; + border-radius: 8px; + padding: 8px; +} + +.mb { + margin-bottom: 12px; +} + +small { + color: #24cc85; +} + +.error { + color: red; + background: black; + padding: 8px; + border-radius: 8px; +} + +@keyframes loading { + 0% { + transform: translateX(0); + opacity: 1; + } + 50% { + transform: translateX(20px); + opacity: 0.5; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} + +.loading { + animation: loading 0.7s infinite; +} diff --git a/examples/wasm-example/src/main.rs b/examples/wasm-example/src/main.rs index 522109f988..d3216cabc1 100644 --- a/examples/wasm-example/src/main.rs +++ b/examples/wasm-example/src/main.rs @@ -1,140 +1,59 @@ -use futures::{self, FutureExt}; - +use routes::signing::SigningExamplesComponent; use yew::prelude::*; +use yew_router::prelude::*; + +use crate::routes::fetching::FetchingExamplesComponent; +mod routes; mod services; -fn main() { - yew::Renderer::::new().render(); +#[derive(Routable, PartialEq, Eq, Clone, Debug)] +pub enum Route { + #[at("/fetching")] + Fetching, + #[at("/signing")] + Signing, + #[not_found] + #[at("/")] + Home, } -struct SubxtExamplesComponent { - operation_title: Option, - lines: Vec, +fn main() { + yew::Renderer::::new().render(); } -enum Message { - Error(subxt::Error), - Reload, - Line(AttrValue), - Lines(Vec), - ButtonClick(Button), -} +struct SubxtExamplesApp; -enum Button { - SubscribeFinalized, - FetchConstant, - FetchEvents, -} +impl Component for SubxtExamplesApp { + type Message = (); -impl Component for SubxtExamplesComponent { - type Message = Message; type Properties = (); fn create(_ctx: &Context) -> Self { - SubxtExamplesComponent { - lines: Vec::new(), - operation_title: None, - } + SubxtExamplesApp } - fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { - match msg { - Message::Error(err) => { - self.lines.push(err.to_string().into()); - } - Message::Reload => { - let window = web_sys::window().expect("Failed to access the window object"); - window - .location() - .reload() - .expect("Failed to reload the page"); - } - Message::Line(line) => { - self.lines.push(line); - } - Message::Lines(mut lines) => { - self.lines.append(&mut lines); - } - Message::ButtonClick(button) => match button { - Button::SubscribeFinalized => { - self.operation_title = Some("Subscribe to finalized blocks:".into()); - let cb: Callback = ctx.link().callback(Message::Line); - ctx.link() - .send_future(services::subscribe_to_finalized_blocks(cb).map(|result| { - let err = result.unwrap_err(); - Message::Error(err) - })); - } - Button::FetchConstant => { - self.operation_title = - Some("Fetch the constant \"block_length\" of \"System\" pallet:".into()); - ctx.link() - .send_future(services::fetch_constant_block_length().map(|result| { - match result { - Ok(value) => Message::Line( - format!( - "constant \"block_length\" of \"System\" pallet:\n {value}" - ) - .into(), - ), - Err(err) => Message::Error(err), - } - })) - } - Button::FetchEvents => { - self.operation_title = Some("Fetch events:".into()); - ctx.link() - .send_future(services::fetch_events_dynamically().map( - |result| match result { - Ok(value) => { - Message::Lines(value.into_iter().map(AttrValue::from).collect()) - } - Err(err) => Message::Error(err), - }, - )) - } - }, + fn view(&self, _ctx: &Context) -> Html { + html! { + + render={switch} /> + } - true } +} - fn view(&self, ctx: &Context) -> Html { - let reload: Callback = ctx.link().callback(|_| Message::Reload); - - let subscribe_finalized = ctx - .link() - .callback(|_| Message::ButtonClick(Button::SubscribeFinalized)); - - let fetch_constant = ctx - .link() - .callback(|_| Message::ButtonClick(Button::FetchConstant)); - - let fetch_events = ctx - .link() - .callback(|_| Message::ButtonClick(Button::FetchEvents)); - - html! { +fn switch(routes: Route) -> Html { + match routes { + Route::Fetching => { + html! { } + } + Route::Signing => html! { }, + Route::Home => { + html! {
- if let Some(operation_title) = &self.operation_title{ - -

{operation_title}

- if self.lines.is_empty(){ -

{"Loading..."}

- } - else{ - - } - { for self.lines.iter().map(|line| html! {

{line}

}) } - } - else{ - <> -

{"Subxt Examples"}

- - - - - } -
+

{"Welcome to the Subxt WASM examples!"}

+ + + } } } } diff --git a/examples/wasm-example/src/routes/fetching.rs b/examples/wasm-example/src/routes/fetching.rs new file mode 100644 index 0000000000..d196c97cfd --- /dev/null +++ b/examples/wasm-example/src/routes/fetching.rs @@ -0,0 +1,140 @@ +use futures::FutureExt; +use yew::prelude::*; + +use crate::services; + +pub struct FetchingExamplesComponent { + operation_title: Option, + lines: Vec, +} + +pub enum Message { + Error(subxt::Error), + Reload, + Line(AttrValue), + Lines(Vec), + ButtonClick(Button), +} + +pub enum Button { + SubscribeFinalized, + FetchConstant, + FetchEvents, +} + +impl Component for FetchingExamplesComponent { + type Message = Message; + type Properties = (); + + fn create(_ctx: &Context) -> Self { + FetchingExamplesComponent { + lines: Vec::new(), + operation_title: None, + } + } + + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { + match msg { + Message::Error(err) => { + self.lines.insert(0, err.to_string().into()); + } + Message::Reload => { + let window = web_sys::window().expect("Failed to access the window object"); + window + .location() + .reload() + .expect("Failed to reload the page"); + } + Message::Line(line) => { + // newer lines go to the top + self.lines.insert(0, line); + } + Message::Lines(lines) => { + for line in lines { + self.lines.insert(0, line); + } + } + Message::ButtonClick(button) => match button { + Button::SubscribeFinalized => { + self.operation_title = Some("Subscribe to finalized blocks:".into()); + let cb: Callback = ctx.link().callback(Message::Line); + ctx.link() + .send_future(services::subscribe_to_finalized_blocks(cb).map(|result| { + let err = result.unwrap_err(); + Message::Error(err) + })); + } + Button::FetchConstant => { + self.operation_title = + Some("Fetch the constant \"block_length\" of \"System\" pallet:".into()); + ctx.link() + .send_future(services::fetch_constant_block_length().map(|result| { + match result { + Ok(value) => Message::Line( + format!( + "constant \"block_length\" of \"System\" pallet:\n {value}" + ) + .into(), + ), + Err(err) => Message::Error(err), + } + })) + } + Button::FetchEvents => { + self.operation_title = Some("Fetch events:".into()); + ctx.link() + .send_future(services::fetch_events_dynamically().map( + |result| match result { + Ok(value) => { + Message::Lines(value.into_iter().map(AttrValue::from).collect()) + } + Err(err) => Message::Error(err), + }, + )) + } + }, + } + true + } + + fn view(&self, ctx: &Context) -> Html { + let reload: Callback = ctx.link().callback(|_| Message::Reload); + + let subscribe_finalized = ctx + .link() + .callback(|_| Message::ButtonClick(Button::SubscribeFinalized)); + + let fetch_constant = ctx + .link() + .callback(|_| Message::ButtonClick(Button::FetchConstant)); + + let fetch_events = ctx + .link() + .callback(|_| Message::ButtonClick(Button::FetchEvents)); + + html! { +
+ if let Some(operation_title) = &self.operation_title{ + +

{operation_title}

+ if self.lines.is_empty(){ +

{"Loading..."}

+ } + else{ + + } + { for self.lines.iter().map(|line| html! {

{line}

}) } + } + else{ + <> + +

{"Subxt Fetching and Subscribing Examples"}

+ + + + + } +
+ } + } +} diff --git a/examples/wasm-example/src/routes/mod.rs b/examples/wasm-example/src/routes/mod.rs new file mode 100644 index 0000000000..9c045fb079 --- /dev/null +++ b/examples/wasm-example/src/routes/mod.rs @@ -0,0 +1,2 @@ +pub mod fetching; +pub mod signing; diff --git a/examples/wasm-example/src/routes/signing.rs b/examples/wasm-example/src/routes/signing.rs new file mode 100644 index 0000000000..44fe024a56 --- /dev/null +++ b/examples/wasm-example/src/routes/signing.rs @@ -0,0 +1,391 @@ +use anyhow::anyhow; +use futures::FutureExt; + +use subxt::{OnlineClient, PolkadotConfig}; + +use subxt::ext::codec::{Decode, Encode}; +use subxt::tx::SubmittableExtrinsic; +use subxt::tx::TxPayload; +use subxt::utils::{AccountId32, MultiSignature}; + +use crate::services::{extension_signature_for_partial_extrinsic, get_accounts, polkadot, Account}; +use web_sys::HtmlInputElement; +use yew::prelude::*; + +pub struct SigningExamplesComponent { + message: String, + remark_call_bytes: Vec, + online_client: Option>, + stage: SigningStage, +} + +impl SigningExamplesComponent { + /// # Panics + /// panics if self.online_client is None. + fn set_message(&mut self, message: String) { + let remark_call = polkadot::tx().system().remark(message.as_bytes().to_vec()); + let online_client = self.online_client.as_ref().unwrap(); + let remark_call_bytes = remark_call + .encode_call_data(&online_client.metadata()) + .unwrap(); + self.remark_call_bytes = remark_call_bytes; + self.message = message; + } +} + +pub enum SigningStage { + Error(String), + CreatingOnlineClient, + EnterMessage, + RequestingAccounts, + SelectAccount(Vec), + Signing(Account), + SigningSuccess { + signer_account: Account, + signature: MultiSignature, + signed_extrinsic_hex: String, + submitting_stage: SubmittingStage, + }, +} + +pub enum SubmittingStage { + Initial { + signed_extrinsic: SubmittableExtrinsic>, + }, + Submitting, + Success { + remark_event: polkadot::system::events::ExtrinsicSuccess, + }, + Error(anyhow::Error), +} + +pub enum Message { + Error(anyhow::Error), + OnlineClientCreated(OnlineClient), + ChangeMessage(String), + RequestAccounts, + ReceivedAccounts(Vec), + /// usize represents account index in Vec + SignWithAccount(usize), + ReceivedSignature( + MultiSignature, + SubmittableExtrinsic>, + ), + SubmitSigned, + ExtrinsicFinalized { + remark_event: polkadot::system::events::ExtrinsicSuccess, + }, + ExtrinsicFailed(anyhow::Error), +} + +impl Component for SigningExamplesComponent { + type Message = Message; + + type Properties = (); + + fn create(ctx: &Context) -> Self { + ctx.link().send_future(OnlineClient::::new().map(|res| { + match res { + Ok(online_client) => Message::OnlineClientCreated(online_client), + Err(err) => Message::Error(anyhow!("Online Client could not be created. Make sure you have a local node running:\n{err}")), + } + })); + SigningExamplesComponent { + message: "".to_string(), + stage: SigningStage::CreatingOnlineClient, + online_client: None, + remark_call_bytes: vec![], + } + } + + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { + match msg { + Message::OnlineClientCreated(online_client) => { + self.online_client = Some(online_client); + self.stage = SigningStage::EnterMessage; + self.set_message("Hello".into()); + } + Message::ChangeMessage(message) => { + self.set_message(message); + } + Message::RequestAccounts => { + self.stage = SigningStage::RequestingAccounts; + ctx.link().send_future(get_accounts().map( + |accounts_or_err| match accounts_or_err { + Ok(accounts) => Message::ReceivedAccounts(accounts), + Err(err) => Message::Error(err), + }, + )); + } + Message::ReceivedAccounts(accounts) => { + self.stage = SigningStage::SelectAccount(accounts); + } + Message::Error(err) => self.stage = SigningStage::Error(err.to_string()), + Message::SignWithAccount(i) => { + if let SigningStage::SelectAccount(accounts) = &self.stage { + let account = accounts.get(i).unwrap(); + let account_address = account.address.clone(); + let account_source = account.source.clone(); + let account_id: AccountId32 = account_address.parse().unwrap(); + + self.stage = SigningStage::Signing(account.clone()); + + let remark_call = polkadot::tx() + .system() + .remark(self.message.as_bytes().to_vec()); + + let api = self.online_client.as_ref().unwrap().clone(); + + ctx.link() + .send_future( + async move { + let partial_extrinsic = + match api.tx().create_partial_signed(&remark_call, &account_id, Default::default()).await { + Ok(partial_extrinsic) => partial_extrinsic, + Err(err) => { + return Message::Error(anyhow!("could not create partial extrinsic:\n{:?}", err)); + } + }; + + let Ok(signature) = extension_signature_for_partial_extrinsic(&partial_extrinsic, &api, &account_id, account_source, account_address).await else { + return Message::Error(anyhow!("Signing via extension failed")); + }; + + let Ok(multi_signature) = MultiSignature::decode(&mut &signature[..]) else { + return Message::Error(anyhow!("MultiSignature Decoding")); + }; + + let signed_extrinsic = partial_extrinsic.sign_with_address_and_signature(&account_id.into(), &multi_signature); + + // do a dry run (to debug in the js console if the extrinsic would work) + let dry_res = signed_extrinsic.dry_run(None).await; + web_sys::console::log_1(&format!("Dry Run Result: {:?}", dry_res).into()); + + // return the signature and signed extrinsic + Message::ReceivedSignature(multi_signature, signed_extrinsic) + } + ); + } + } + Message::ReceivedSignature(signature, signed_extrinsic) => { + if let SigningStage::Signing(account) = &self.stage { + let signed_extrinsic_hex = + format!("0x{}", hex::encode(signed_extrinsic.encoded())); + self.stage = SigningStage::SigningSuccess { + signer_account: account.clone(), + signature, + signed_extrinsic_hex, + submitting_stage: SubmittingStage::Initial { signed_extrinsic }, + } + } + } + Message::SubmitSigned => { + if let SigningStage::SigningSuccess { + submitting_stage: submitting_stage @ SubmittingStage::Initial { .. }, + .. + } = &mut self.stage + { + let SubmittingStage::Initial { signed_extrinsic } = std::mem::replace(submitting_stage, SubmittingStage::Submitting) else { + panic!("unreachable") + }; + + ctx.link().send_future(async move { + match submit_wait_finalized_and_get_extrinsic_success_event( + signed_extrinsic, + ) + .await + { + Ok(remark_event) => Message::ExtrinsicFinalized { remark_event }, + Err(err) => Message::ExtrinsicFailed(err), + } + }); + } + } + Message::ExtrinsicFinalized { remark_event } => { + if let SigningStage::SigningSuccess { + submitting_stage, .. + } = &mut self.stage + { + *submitting_stage = SubmittingStage::Success { remark_event } + } + } + Message::ExtrinsicFailed(err) => { + if let SigningStage::SigningSuccess { + submitting_stage, .. + } = &mut self.stage + { + *submitting_stage = SubmittingStage::Error(err) + } + } + }; + true + } + + fn view(&self, ctx: &Context) -> Html { + let message_as_hex_html = || { + html!( +
+ {"Hex representation of \"remark\" call in \"System\" pallet:"}
+ {format!("0x{}", hex::encode(&self.remark_call_bytes))} +
+ ) + }; + + let message_html: Html = match &self.stage { + SigningStage::Error(_) + | SigningStage::EnterMessage + | SigningStage::CreatingOnlineClient => html!(<>), + _ => { + let _remark_call = polkadot::tx() + .system() + .remark(self.message.as_bytes().to_vec()); + html!( +
+
+ {"Message: "}
+ {&self.message} +
+ {message_as_hex_html()} +
+ ) + } + }; + + let signer_account_html: Html = match &self.stage { + SigningStage::Signing(signer_account) + | SigningStage::SigningSuccess { signer_account, .. } => { + html!( +
+ {"Account used for signing: "}
+ {"Extension: "}{&signer_account.source}
+ {"Name: "}{&signer_account.name}
+ {"Address: "}{&signer_account.address}
+
+ ) + } + _ => html!(<>), + }; + + let stage_html: Html = match &self.stage { + SigningStage::Error(error_message) => { + html!(
{"Error: "} {error_message}
) + } + SigningStage::CreatingOnlineClient => { + html!( +
+ {"Creating Online Client..."} +
+ ) + } + SigningStage::EnterMessage => { + let get_accounts_click = ctx.link().callback(|_| Message::RequestAccounts); + let on_input = ctx.link().callback(move |event: InputEvent| { + let input_element = event.target_dyn_into::().unwrap(); + let value = input_element.value(); + Message::ChangeMessage(value) + }); + + html!( + <> +
{"Enter a message for the \"remark\" call in the \"System\" pallet:"}
+ + {message_as_hex_html()} + + + ) + } + SigningStage::RequestingAccounts => { + html!(
{"Querying extensions for accounts..."}
) + } + SigningStage::SelectAccount(accounts) => { + if accounts.is_empty() { + html!(
{"No Web3 extension accounts found. Install Talisman or the Polkadot.js extension and add an account."}
) + } else { + html!( + <> +
{"Select an account you want to use for signing:"}
+ { for accounts.iter().enumerate().map(|(i, account)| { + let sign_with_account = ctx.link().callback(move |_| Message::SignWithAccount(i)); + html! { + + } + }) } + + ) + } + } + SigningStage::Signing(_) => { + html!(
{"Singing message with browser extension..."}
) + } + SigningStage::SigningSuccess { + signature, + signed_extrinsic_hex, + submitting_stage, + .. + } => { + let submitting_stage_html = match submitting_stage { + SubmittingStage::Initial { .. } => { + let submit_extrinsic_click = + ctx.link().callback(move |_| Message::SubmitSigned); + html!() + } + SubmittingStage::Submitting => { + html!(
{"Submitting Extrinsic... (please wait a few seconds)"}
) + } + SubmittingStage::Success { remark_event } => { + html!(
{"Successfully submitted Extrinsic. Event:"}
{format!("{:?}", remark_event)}
) + } + SubmittingStage::Error(err) => { + html!(
{"Error: "} {err.to_string()}
) + } + }; + + html!( + <> +
+ {"Received signature: "}
+ {hex::encode(signature.encode())} +
+
+ {"Hex representation of signed extrinsic: "}
+ {signed_extrinsic_hex} +
+ {submitting_stage_html} + + ) + } + }; + + html! { +
+ +

{"Subxt Signing Example"}

+ {message_html} + {signer_account_html} + {stage_html} +
+ } + } +} + +async fn submit_wait_finalized_and_get_extrinsic_success_event( + extrinsic: SubmittableExtrinsic>, +) -> Result { + let events = extrinsic + .submit_and_watch() + .await? + .wait_for_finalized_success() + .await?; + + let events_str = format!("{:?}", &events); + web_sys::console::log_1(&events_str.into()); + for event in events.find::() { + web_sys::console::log_1(&format!("{:?}", event).into()); + } + + let success = events.find_first::()?; + success.ok_or(anyhow!("ExtrinsicSuccess not found in events")) +} diff --git a/examples/wasm-example/src/services.rs b/examples/wasm-example/src/services.rs index 96e0d65fc4..b1bd978527 100644 --- a/examples/wasm-example/src/services.rs +++ b/examples/wasm-example/src/services.rs @@ -1,10 +1,19 @@ +use anyhow::anyhow; use futures::StreamExt; +use js_sys::Promise; +use serde::{Deserialize, Serialize}; +use serde_json::json; use std::fmt::Write; +use subxt::ext::codec::Encode; +use subxt::tx::PartialExtrinsic; use subxt::{self, OnlineClient, PolkadotConfig}; +use subxt::utils::AccountId32; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::JsFuture; use yew::{AttrValue, Callback}; #[subxt::subxt(runtime_metadata_path = "../../artifacts/polkadot_metadata_small.scale")] -mod polkadot {} +pub mod polkadot {} pub(crate) async fn fetch_constant_block_length() -> Result { let api = OnlineClient::::new().await?; @@ -71,3 +80,105 @@ pub(crate) async fn subscribe_to_finalized_blocks( } Ok(()) } + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_name = getAccounts)] + pub fn js_get_accounts() -> Promise; + #[wasm_bindgen(js_name = signPayload)] + pub fn js_sign_payload(payload: String, source: String, address: String) -> Promise; +} + +/// DTO to communicate with JavaScript +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Account { + /// account name + pub name: String, + /// name of the browser extension + pub source: String, + /// the signature type, e.g. "sr25519" or "ed25519" + pub ty: String, + /// ss58 formatted address as string. Can be converted into AccountId32 via it's FromStr implementation. + pub address: String, +} + +pub async fn get_accounts() -> Result, anyhow::Error> { + let result = JsFuture::from(js_get_accounts()) + .await + .map_err(|js_err| anyhow!("{js_err:?}"))?; + let accounts_str = result + .as_string() + .ok_or(anyhow!("Error converting JsValue into String"))?; + let accounts: Vec = serde_json::from_str(&accounts_str)?; + Ok(accounts) +} + +fn to_hex(bytes: impl AsRef<[u8]>) -> String { + format!("0x{}", hex::encode(bytes.as_ref())) +} + +fn encode_to_hex(input: &E) -> String { + format!("0x{}", hex::encode(input.encode())) +} + +/// this is used because numeric types (e.g. u32) are encoded as little-endian via scale (e.g. 9430 -> d6240000) +/// while we need a big-endian representation for the json (e.g. 9430 -> 000024d6). +fn encode_to_hex_reverse(input: &E) -> String { + let mut bytes = input.encode(); + bytes.reverse(); + format!("0x{}", hex::encode(bytes)) +} + + +/// communicates with JavaScript to obtain a signature for the `partial_extrinsic` via a browser extension (e.g. polkadot-js or Talisman) +/// +/// Some parameters are hard-coded here and not taken from the partial_extrinsic itself (mortality_checkpoint, era, tip). +pub async fn extension_signature_for_partial_extrinsic( + partial_extrinsic: &PartialExtrinsic>, + api: &OnlineClient, + account_id: &AccountId32, + account_source: String, + account_address: String, +) -> Result, anyhow::Error> { + let spec_version = encode_to_hex_reverse(&api.runtime_version().spec_version); + let transaction_version = encode_to_hex_reverse(&api.runtime_version().transaction_version); + let mortality_checkpoint = encode_to_hex(&api.genesis_hash()); + let era = encode_to_hex(&subxt::config::extrinsic_params::Era::Immortal); + let genesis_hash = encode_to_hex(&api.genesis_hash()); + let method = to_hex(partial_extrinsic.call_data()); + let nonce = api.tx().account_nonce(account_id).await?; + let nonce = encode_to_hex_reverse(&nonce); + let signed_extensions: Vec = api + .metadata() + .extrinsic() + .signed_extensions() + .iter() + .map(|e| e.identifier().to_string()) + .collect(); + let tip = encode_to_hex(&subxt::config::polkadot::PlainTip::new(0)); + + let payload = json!({ + "specVersion": spec_version, + "transactionVersion": transaction_version, + "address": account_address, + "blockHash": mortality_checkpoint, + "blockNumber": "0x00000000", + "era": era, + "genesisHash": genesis_hash, + "method": method, + "nonce": nonce, + "signedExtensions": signed_extensions, + "tip": tip, + "version": 4, + }); + + let payload = payload.to_string(); + let result = JsFuture::from(js_sign_payload(payload, account_source, account_address)) + .await + .map_err(|js_err| anyhow!("{js_err:?}"))?; + let signature = result + .as_string() + .ok_or(anyhow!("Error converting JsValue into String"))?; + let signature = hex::decode(&signature[2..])?; + Ok(signature) +} diff --git a/subxt/src/config/extrinsic_params.rs b/subxt/src/config/extrinsic_params.rs index 7b6bc1b1ea..6dc16ec196 100644 --- a/subxt/src/config/extrinsic_params.rs +++ b/subxt/src/config/extrinsic_params.rs @@ -57,12 +57,20 @@ pub trait ExtrinsicParams: Debug + 'static { #[derive(Derivative)] #[derivative(Debug(bound = "Tip: Debug"))] pub struct BaseExtrinsicParams { + /// Era defines how long the transaction will be valid for. era: Era, + /// Nonce (account nonce sent along an extrinsic, such that no extrinsic is submitted twice) nonce: u64, + /// The tip you would like to give to the block author for this transaction. + /// Note: Can be zero. tip: Tip, + /// spec version spec_version: u32, + /// transaction version transaction_version: u32, + /// genesis hash of the chain genesis_hash: T::Hash, + /// The block after which the transaction becomes valid. mortality_checkpoint: T::Hash, marker: std::marker::PhantomData, } diff --git a/subxt/src/tx/mod.rs b/subxt/src/tx/mod.rs index 0eb75c3496..63b0130658 100644 --- a/subxt/src/tx/mod.rs +++ b/subxt/src/tx/mod.rs @@ -21,7 +21,7 @@ pub use self::signer::PairSigner; pub use self::{ signer::Signer, - tx_client::{SubmittableExtrinsic, TxClient}, + tx_client::{PartialExtrinsic, SubmittableExtrinsic, TxClient}, tx_payload::{dynamic, BoxedPayload, DynamicPayload, Payload, TxPayload}, tx_progress::{TxInBlock, TxProgress, TxStatus}, }; diff --git a/subxt/src/tx/tx_client.rs b/subxt/src/tx/tx_client.rs index 91c3e40b0d..7260a7e848 100644 --- a/subxt/src/tx/tx_client.rs +++ b/subxt/src/tx/tx_client.rs @@ -189,7 +189,7 @@ where // custom decoding from a u16/u32/u64 into a u64, based on the number of bytes we got back. let cursor = &mut &account_nonce_bytes[..]; - let account_nonce: u64 = match account_nonce_bytes.len(){ + let account_nonce: u64 = match account_nonce_bytes.len() { 2 => u16::decode(cursor)?.into(), 4 => u32::decode(cursor)?.into(), 8 => u64::decode(cursor)?,