From cdb64008a287392b076b0cb7af056aeaba598415 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 12 Dec 2025 15:08:34 -0300 Subject: [PATCH 01/27] improve router --- rpc-router/Cargo.lock | 1763 ++++++++++++++++++++++++++++++++++++++++ rpc-router/Cargo.toml | 9 +- rpc-router/src/main.rs | 262 +++++- 3 files changed, 1993 insertions(+), 41 deletions(-) create mode 100644 rpc-router/Cargo.lock diff --git a/rpc-router/Cargo.lock b/rpc-router/Cargo.lock new file mode 100644 index 0000000..0033c4d --- /dev/null +++ b/rpc-router/Cargo.lock @@ -0,0 +1,1763 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "cc" +version = "1.2.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-layer", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "reqwest" +version = "0.12.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower 0.5.2", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rpc-router" +version = "0.1.0" +dependencies = [ + "anyhow", + "base64", + "http-body-util", + "hyper", + "hyper-util", + "reqwest", + "serde", + "serde_json", + "tokio", + "tower 0.4.13", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[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.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rpc-router/Cargo.toml b/rpc-router/Cargo.toml index b60295b..3e4ee46 100644 --- a/rpc-router/Cargo.toml +++ b/rpc-router/Cargo.toml @@ -1,16 +1,19 @@ [package] name = "rpc-router" +description = "Z3 RPC request router" version = "0.1.0" edition = "2021" [dependencies] -tokio = { version = "1.36", features = ["full"] } +anyhow = "1.0" +base64 = "0.22" +http-body-util = "0.1" hyper = { version = "1.2", features = ["full"] } hyper-util = { version = "0.1", features = ["full"] } +reqwest = "0.12" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +tokio = { version = "1.36", features = ["full"] } tower = { version = "0.4", features = ["util"] } -http-body-util = "0.1" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -anyhow = "1.0" diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 5f0179c..a572401 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -1,17 +1,24 @@ +use std::{env, net::SocketAddr, sync::Arc}; + use anyhow::Result; +use base64::{engine::general_purpose, Engine as _}; use http_body_util::{BodyExt, Full}; -use hyper::body::Bytes; -use hyper::server::conn::http1; -use hyper::service::service_fn; -use hyper::{Request, Response, StatusCode}; -use hyper_util::rt::TokioIo; +use hyper::{ + body::Bytes, + header::{HeaderName, HeaderValue}, + server::conn::http1, + service::service_fn, + Request, Response, StatusCode, Uri, +}; +use hyper_util::{ + client::legacy::Client as HyperClient, + rt::{TokioExecutor, TokioIo}, +}; +use reqwest::Client as ReqwestClient; use serde::Deserialize; -use std::env; -use std::net::SocketAddr; -use std::sync::Arc; +use serde_json::{json, Value}; use tokio::net::TcpListener; use tracing::{error, info, warn}; -use hyper::Uri; #[derive(Deserialize, Debug)] struct RpcRequest { @@ -28,18 +35,36 @@ struct Config { impl Config { fn from_env() -> Self { Self { - zebra_url: env::var("ZEBRA_URL").unwrap_or_else(|_| "http://zebra:18232".to_string()), - zallet_url: env::var("ZALLET_URL").unwrap_or_else(|_| "http://zallet:28232".to_string()), + zebra_url: env::var("ZEBRA_URL") + .unwrap_or_else(|_| "http://127.0.0.1:20617".to_string()), + zallet_url: env::var("ZALLET_URL") + .unwrap_or_else(|_| "http://127.0.0.1:25617".to_string()), zaino_url: env::var("ZAINO_URL").unwrap_or_else(|_| "http://zaino:8237".to_string()), } } } -async fn forward_request(req: Request>, target_url: &str) -> Result>> { - let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()) - .build_http(); +#[derive(Clone)] +struct Z3Schema { + zebra_methods: Vec, + zallet_methods: Vec, + merged: Value, +} + +async fn forward_request( + req: Request>, + target_url: &str, +) -> Result>> { + let client = HyperClient::builder(TokioExecutor::new()).build_http(); - let uri_string = format!("{}{}", target_url, req.uri().path_and_query().map(|x| x.as_str()).unwrap_or("/")); + let uri_string = format!( + "{}{}", + target_url, + req.uri() + .path_and_query() + .map(|x| x.as_str()) + .unwrap_or("/") + ); let uri: Uri = uri_string.parse()?; let (parts, body) = req.into_parts(); @@ -48,6 +73,14 @@ async fn forward_request(req: Request>, target_url: &str) -> Result< .uri(uri) .version(parts.version); + // Inject auth header + let auth = general_purpose::STANDARD.encode("zebra:zebra"); + new_req = new_req.header( + hyper::header::AUTHORIZATION, + hyper::header::HeaderValue::from_str(&format!("Basic {}", auth))?, + ); + + // Copy other headers for (k, v) in parts.headers { if let Some(key) = k { new_req = new_req.header(key, v); @@ -56,20 +89,54 @@ async fn forward_request(req: Request>, target_url: &str) -> Result< let new_req = new_req.body(body)?; let res = client.request(new_req).await?; - + let (parts, body) = res.into_parts(); let body_bytes = body.collect().await?.to_bytes(); let new_res = Response::from_parts(parts, Full::new(body_bytes)); Ok(new_res) } +fn add_cors_headers(mut resp: Response>) -> Response> { + let headers = resp.headers_mut(); + for &(name, value) in &[ + ( + "access-control-allow-origin", + "https://playground.open-rpc.org", + ), + ("access-control-allow-methods", "POST, OPTIONS"), + ("access-control-allow-headers", "Content-Type"), + ("access-control-max-age", "86400"), + ] { + headers.insert( + HeaderName::from_static(name), + HeaderValue::from_static(value), + ); + } + + resp +} -async fn handler(req: Request, config: Arc) -> Result>> { +async fn handler( + req: Request, + config: Arc, + z3: Z3Schema, +) -> Result>> { // Health check if req.uri().path() == "/health" { return Ok(Response::new(Full::new(Bytes::from("OK")))); } + // Handle CORS preflight + if req.method() == hyper::Method::OPTIONS { + let resp = add_cors_headers( + Response::builder() + .status(StatusCode::NO_CONTENT) + .body(Full::new(Bytes::new())) + .unwrap(), + ); + return Ok(resp); + } + // Only handle POST requests for JSON-RPC if req.method() != hyper::Method::POST { return Ok(Response::builder() @@ -81,26 +148,38 @@ async fn handler(req: Request, config: Arc) -> Re // Buffer the body to parse it let (parts, body) = req.into_parts(); let body_bytes = body.collect().await?.to_bytes(); - - // todo: move the map of methods to service config + // Attempt to parse method from body let target_url = if let Ok(rpc_req) = serde_json::from_slice::(&body_bytes) { - match rpc_req.method.as_str() { - // Zallet (Wallet) methods - "z_sendmany" | "getnewaddress" | "z_listreceivedbyaddress" | "z_getbalance" | "z_gettotalbalance" | "z_getoperationresult" | "z_getoperationstatus" | "z_listoperationids" | "z_validateaddress" => { - info!("Routing {} to Zallet", rpc_req.method); - &config.zallet_url - }, - // Zaino (Indexer) methods - "getaddressbalance" | "getaddresstxids" | "getaddressutxos" | "getaddressdeltas" | "getaddressmempool" => { - info!("Routing {} to Zaino", rpc_req.method); - &config.zaino_url - }, - // Default to Zebra for everything else (getblock, sendrawtransaction, getinfo, etc.) - method => { - info!("Routing {} to Zebra", method); - &config.zebra_url - } + if rpc_req.method == "rpc.discover" { + info!("Routing rpc.discover to merged schema"); + + return Ok(add_cors_headers( + Response::builder() + .status(StatusCode::OK) + .header(hyper::header::CONTENT_TYPE, "application/json") + .body(Full::new(Bytes::from(serde_json::to_string(&z3.merged)?))) + .expect("z3 merged schema response should be valid"), + )); + } + + if let Some(_method) = z3 + .zebra_methods + .iter() + .find(|m| m["name"] == rpc_req.method) + { + info!("Routing {} to Zebra", rpc_req.method); + &config.zebra_url + } else if let Some(_method) = z3 + .zallet_methods + .iter() + .find(|m| m["name"] == rpc_req.method) + { + info!("Routing {} to Zallet", rpc_req.method); + &config.zallet_url + } else { + info!("Routing {} to Zaino", rpc_req.method); + &config.zaino_url } } else { warn!("Failed to parse JSON-RPC body, defaulting to Zebra"); @@ -109,11 +188,12 @@ async fn handler(req: Request, config: Arc) -> Re // Reconstruct request with buffered body let new_req = Request::from_parts(parts, Full::new(body_bytes)); - + match forward_request(new_req, target_url).await { - Ok(res) => Ok(res), + Ok(res) => Ok(add_cors_headers(res)), Err(e) => { error!("Forwarding error: {}", e); + Ok(Response::builder() .status(StatusCode::BAD_GATEWAY) .body(Full::new(Bytes::from(format!("Bad Gateway: {}", e)))) @@ -122,6 +202,101 @@ async fn handler(req: Request, config: Arc) -> Re } } +async fn call_rpc_discover(url: &str) -> Result { + let client = ReqwestClient::new(); + + let body = json!({ + "jsonrpc": "2.0", + "id": 1, + "method": "rpc.discover", + "params": [] + }); + + let text = client + .post(url) + .basic_auth("zebra", Some("zebra")) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .body(body.to_string()) + .send() + .await? + .error_for_status()? + .text() + .await?; + + let resp = serde_json::from_str::(&text)?; + + Ok(resp) +} + +fn extract_methods_array(schema: &Value) -> Vec { + schema["methods"].as_array().cloned().unwrap_or_default() +} + +fn annotate_methods_with_server(methods: &mut Vec, server_name: &str) { + for m in methods { + m.as_object_mut() + .unwrap() + .insert("x-server".to_string(), json!(server_name)); + } +} + +fn merge_components_schemas(schema: &Value, combined: &mut serde_json::Map) { + if let Some(obj) = schema["components"]["schemas"].as_object() { + for (k, v) in obj { + combined.insert(k.clone(), v.clone()); + } + } +} + +fn merge_openrpc_schemas(zebra: Value, zallet: Value) -> Result { + // Extract method arrays + let mut zebra_methods = extract_methods_array(&zebra); + let mut zallet_methods = extract_methods_array(&zallet); + + // Annotate each method with its origin + annotate_methods_with_server(&mut zebra_methods, "zebra"); + annotate_methods_with_server(&mut zallet_methods, "zallet"); + + // Merge schemas under components.schemas + let mut combined_schemas = serde_json::Map::new(); + merge_components_schemas(&zebra, &mut combined_schemas); + merge_components_schemas(&zallet, &mut combined_schemas); + + let mut combined_methods = Vec::new(); + combined_methods.extend(zebra_methods.clone()); + combined_methods.extend(zallet_methods.clone()); + + // Build final merged schema + let merged = json!({ + "openrpc": zebra["openrpc"].clone(), + "info": { + "title": env!("CARGO_PKG_NAME"), + "description": env!("CARGO_PKG_DESCRIPTION"), + "version": env!("CARGO_PKG_VERSION"), + }, + "servers": [ + { "name": "router", "url": "http://localhost:8080/" }, + ], + "methods": combined_methods, + "components": { + "schemas": combined_schemas + } + }); + + let z3 = Z3Schema { + zebra_methods, + zallet_methods, + merged: Value::Object( + merged + .as_object() + .expect("merged object should be valid") + .clone(), + ), + }; + + Ok(z3) +} + #[tokio::main] async fn main() -> Result<()> { tracing_subscriber::fmt::init(); @@ -129,6 +304,13 @@ async fn main() -> Result<()> { let config = Arc::new(Config::from_env()); let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); + let zebra_schema = call_rpc_discover(&config.zebra_url).await?["result"].clone(); + let zallet_schema = call_rpc_discover(&config.zallet_url).await?["result"].clone(); + + let z3 = merge_openrpc_schemas(zebra_schema, zallet_schema)?; + + println!("{}", serde_json::to_string_pretty(&z3.merged)?); + let listener = TcpListener::bind(addr).await?; info!("RPC Router listening on {}", addr); @@ -137,9 +319,13 @@ async fn main() -> Result<()> { let io = TokioIo::new(stream); let config = config.clone(); + let z3 = z3.clone(); tokio::task::spawn(async move { if let Err(err) = http1::Builder::new() - .serve_connection(io, service_fn(move |req| handler(req, config.clone()))) + .serve_connection( + io, + service_fn(move |req| handler(req, config.clone(), z3.clone())), + ) .await { error!("Error serving connection: {:?}", err); From 870429b595852d0b25b1eb0b455aaea8ae2816d9 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 12 Dec 2025 16:02:44 -0300 Subject: [PATCH 02/27] add some docs --- rpc-router/src/main.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index a572401..e7a6e1a 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -1,3 +1,8 @@ +//! RPC Router for Zebra, Zallet and Zaino. +//! +//! This service listens for JSON-RPC requests and routes them to the appropriate backend +//! based on the method being called. It merges the OpenRPC schemas from Zebra and Zallet +//! to determine which methods belong to which service. use std::{env, net::SocketAddr, sync::Arc}; use anyhow::Result; @@ -20,11 +25,13 @@ use serde_json::{json, Value}; use tokio::net::TcpListener; use tracing::{error, info, warn}; +/// Structure to parse incoming JSON-RPC requests. #[derive(Deserialize, Debug)] struct RpcRequest { method: String, } +/// Configuration for the RPC router. #[derive(Clone)] struct Config { zebra_url: String, @@ -44,6 +51,7 @@ impl Config { } } +/// Merged schema and method lists for routing. #[derive(Clone)] struct Z3Schema { zebra_methods: Vec, @@ -51,6 +59,7 @@ struct Z3Schema { merged: Value, } +/// Forwards the incoming request to the specified target URL with basic auth. async fn forward_request( req: Request>, target_url: &str, @@ -96,6 +105,8 @@ async fn forward_request( Ok(new_res) } + +/// Adds CORS headers to the response. fn add_cors_headers(mut resp: Response>) -> Response> { let headers = resp.headers_mut(); for &(name, value) in &[ @@ -116,6 +127,7 @@ fn add_cors_headers(mut resp: Response>) -> Response> { resp } +/// Main request handler. async fn handler( req: Request, config: Arc, @@ -202,6 +214,7 @@ async fn handler( } } +/// Calls rpc.discover on the given URL and returns the parsed JSON response. async fn call_rpc_discover(url: &str) -> Result { let client = ReqwestClient::new(); @@ -228,10 +241,12 @@ async fn call_rpc_discover(url: &str) -> Result { Ok(resp) } +/// Extracts the methods array from the OpenRPC schema. fn extract_methods_array(schema: &Value) -> Vec { schema["methods"].as_array().cloned().unwrap_or_default() } +/// Annotates each method with its origin server. fn annotate_methods_with_server(methods: &mut Vec, server_name: &str) { for m in methods { m.as_object_mut() @@ -240,6 +255,7 @@ fn annotate_methods_with_server(methods: &mut Vec, server_name: &str) { } } +/// Merges the components.schemas from the given schema into the combined map. fn merge_components_schemas(schema: &Value, combined: &mut serde_json::Map) { if let Some(obj) = schema["components"]["schemas"].as_object() { for (k, v) in obj { @@ -248,6 +264,7 @@ fn merge_components_schemas(schema: &Value, combined: &mut serde_json::Map Result { // Extract method arrays let mut zebra_methods = extract_methods_array(&zebra); From 679b29a0fb202ddef8052b11c0468206f658d4a0 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 17 Dec 2025 18:53:20 -0300 Subject: [PATCH 03/27] add merged schema --- rpc-router/src/main.rs | 8 +- rpc-router/z3_merged.json | 3578 +++++++++++++++++++++++++++++++++++++ 2 files changed, 3583 insertions(+), 3 deletions(-) create mode 100644 rpc-router/z3_merged.json diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index e7a6e1a..80f7ee1 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -43,9 +43,9 @@ impl Config { fn from_env() -> Self { Self { zebra_url: env::var("ZEBRA_URL") - .unwrap_or_else(|_| "http://127.0.0.1:20617".to_string()), + .unwrap_or_else(|_| "http://127.0.0.1:20251".to_string()), zallet_url: env::var("ZALLET_URL") - .unwrap_or_else(|_| "http://127.0.0.1:25617".to_string()), + .unwrap_or_else(|_| "http://127.0.0.1:25251".to_string()), zaino_url: env::var("ZAINO_URL").unwrap_or_else(|_| "http://zaino:8237".to_string()), } } @@ -326,7 +326,9 @@ async fn main() -> Result<()> { let z3 = merge_openrpc_schemas(zebra_schema, zallet_schema)?; - println!("{}", serde_json::to_string_pretty(&z3.merged)?); + let file_path = "z3_merged.json"; + tokio::fs::write(file_path, serde_json::to_string_pretty(&z3.merged)?).await?; + info!("Saved merged schema to {}", file_path); let listener = TcpListener::bind(addr).await?; info!("RPC Router listening on {}", addr); diff --git a/rpc-router/z3_merged.json b/rpc-router/z3_merged.json new file mode 100644 index 0000000..c580d7d --- /dev/null +++ b/rpc-router/z3_merged.json @@ -0,0 +1,3578 @@ +{ + "components": { + "schemas": { + "Account": { + "description": "Information about the new account.", + "properties": { + "account": { + "description": "The new account's ZIP 32 account index.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "account_uuid": { + "description": "The new account's UUID within this Zallet instance.", + "type": "string" + } + }, + "required": [ + "account_uuid" + ], + "type": "object" + }, + "Account2": { + "properties": { + "account": { + "description": "The ZIP 32 account ID.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "account_uuid": { + "description": "The account's UUID within this Zallet instance.", + "type": "string" + }, + "addresses": { + "items": { + "$ref": "#/components/schemas/Address2" + }, + "type": "array" + } + }, + "required": [ + "account_uuid", + "addresses" + ], + "type": "object" + }, + "Account3": { + "properties": { + "account_uuid": { + "description": "The account's UUID within this Zallet instance.", + "type": "string" + }, + "seedfp": { + "type": "string" + }, + "zip32_account_index": { + "description": "The account's ZIP 32 account index.", + "format": "uint32", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "account_uuid", + "seedfp", + "zip32_account_index" + ], + "type": "object" + }, + "AccountEffect": { + "description": "The effect of a transaction on an account's balance.", + "properties": { + "delta": { + "description": "The net change of the account's balance, in ZEC.\n\nThis includes any contribution by this account to the transaction fee.", + "type": "number" + }, + "deltaZat": { + "description": "The net change of the account's balance, in zatoshis.\n\nThis includes any contribution by this account to the transaction fee.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "delta", + "deltaZat" + ], + "type": "object" + }, + "AccountParameter": { + "properties": { + "birthday_height": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "name": { + "type": "string" + }, + "seedfp": { + "type": "string" + }, + "zip32_account_index": { + "format": "uint32", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "name", + "seedfp", + "zip32_account_index", + "birthday_height" + ], + "type": "object" + }, + "Accounts": { + "description": "The list of recovered accounts.", + "properties": { + "accounts": { + "items": { + "$ref": "#/components/schemas/Account3" + }, + "type": "array" + } + }, + "required": [ + "accounts" + ], + "type": "object" + }, + "AddNodeCommand": { + "description": "Commands for the `addnode` RPC method.", + "oneOf": [ + { + "const": "add", + "description": "Add a node to the address book.", + "type": "string" + } + ] + }, + "Address": { + "description": "Information about a derived Unified Address.", + "properties": { + "account": { + "description": "The ZIP 32 account ID.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "account_uuid": { + "description": "The account's UUID within this Zallet instance.", + "type": "string" + }, + "address": { + "description": "The unified address corresponding to the diversifier.", + "type": "string" + }, + "diversifier_index": { + "description": "The diversifier index specified or chosen.", + "format": "uint128", + "minimum": 0, + "type": "integer" + }, + "receiver_types": { + "description": "The receiver types that the UA contains (valid values are \"p2pkh\", \"sapling\", \"orchard\").", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "account_uuid", + "diversifier_index", + "receiver_types", + "address" + ], + "type": "object" + }, + "Address2": { + "properties": { + "diversifier_index": { + "description": "A diversifier index used in the account.", + "format": "uint128", + "minimum": 0, + "type": "integer" + }, + "ua": { + "description": "The unified address corresponding to the diversifier.", + "type": "string" + } + }, + "required": [ + "diversifier_index", + "ua" + ], + "type": "object" + }, + "AddressSource": { + "properties": { + "derived_transparent": { + "description": "Each element in this list represents a set of transparent addresses derived from a\nsingle BIP 44 account index.", + "items": { + "$ref": "#/components/schemas/DerivedTransparentAddresses" + }, + "type": "array" + }, + "sapling": { + "description": "Each element in this list represents a set of diversified addresses derived from a\nsingle IVK.", + "items": { + "$ref": "#/components/schemas/SaplingAddresses" + }, + "type": "array" + }, + "source": { + "type": "string" + }, + "transparent": { + "anyOf": [ + { + "$ref": "#/components/schemas/TransparentAddresses" + }, + { + "type": "null" + } + ], + "description": "This object contains transparent addresses for which we have no derivation\ninformation." + }, + "unified": { + "description": "Each element in this list represents a set of diversified Unified Addresses\nderived from a single UFVK.", + "items": { + "$ref": "#/components/schemas/UnifiedAddresses" + }, + "type": "array" + } + }, + "required": [ + "source", + "derived_transparent", + "sapling", + "unified" + ], + "type": "object" + }, + "AmountParameter": { + "properties": { + "address": { + "description": "A taddr, zaddr, or Unified Address.", + "type": "string" + }, + "amount": { + "description": "The numeric amount in ZEC." + }, + "memo": { + "description": "If the address is a zaddr, raw data represented in hexadecimal string format. If\nthe output is being sent to a transparent address, it’s an error to include this\nfield.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "address", + "amount" + ], + "type": "object" + }, + "DerivedTransparentAddresses": { + "properties": { + "account": { + "description": "The BIP 44 account index.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "changeAddresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ephemeralAddresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "seedfp": { + "type": "string" + } + }, + "required": [ + "seedfp", + "account", + "addresses", + "changeAddresses", + "ephemeralAddresses" + ], + "type": "object" + }, + "GetAddressBalanceRequest": { + "anyOf": [ + { + "description": "A list of address strings.", + "properties": { + "addresses": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "addresses" + ], + "type": "object" + }, + { + "description": "A single address string.", + "type": "string" + } + ], + "description": "A request for [`RpcServer::get_address_balance`]." + }, + "GetAddressTxIdsRequest": { + "anyOf": [ + { + "description": "A single address string.", + "type": "string" + }, + { + "description": "A full request object with address list and optional height range.", + "properties": { + "addresses": { + "description": "A list of addresses to get transactions from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "end": { + "description": "The height to end looking for transactions.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "start": { + "description": "The height to start looking for transactions.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "required": [ + "addresses" + ], + "type": "object" + } + ], + "description": "Parameters of [`RpcServer::get_address_tx_ids`] RPC method.\n\nSee [`RpcServer::get_address_tx_ids`] for more details." + }, + "GetAddressUtxosRequest": { + "anyOf": [ + { + "description": "A single address string.", + "type": "string" + }, + { + "description": "A full request object with address list and chainInfo flag.", + "properties": { + "addresses": { + "description": "A list of addresses to get transactions from.", + "items": { + "type": "string" + }, + "type": "array" + }, + "chainInfo": { + "default": false, + "description": "The height to start looking for transactions.", + "type": "boolean" + } + }, + "required": [ + "addresses" + ], + "type": "object" + } + ], + "description": "Parameters of [`RpcServer::get_address_utxos`] RPC method." + }, + "GetBlockTemplateCapability": { + "description": "Valid `capabilities` values that indicate client-side support.", + "oneOf": [ + { + "const": "longpoll", + "description": "Long Polling support.\nCurrently ignored by zebra.", + "type": "string" + }, + { + "const": "coinbasetxn", + "description": "Information for coinbase transaction, default template data with the `coinbasetxn` field.\nCurrently ignored by zebra.", + "type": "string" + }, + { + "const": "coinbasevalue", + "description": "Coinbase value, template response provides a `coinbasevalue` field and omits `coinbasetxn` field.\nCurrently ignored by zebra.", + "type": "string" + }, + { + "const": "coinbaseaux", + "description": "Components of the coinbase transaction.\nCurrently ignored by zebra.", + "type": "string" + }, + { + "const": "proposal", + "description": "Currently ignored by zcashd and zebra.", + "type": "string" + }, + { + "const": "serverlist", + "description": "Currently ignored by zcashd and zebra.", + "type": "string" + }, + { + "const": "workid", + "description": "Currently ignored by zcashd and zebra.", + "type": "string" + }, + { + "const": "unknowncapability", + "description": "Unknown capability to fill in for mutations.", + "type": "string" + } + ] + }, + "GetBlockTemplateParameters": { + "description": "Optional parameter `jsonrequestobject` for `getblocktemplate` RPC request.\n\nThe `data` field must be provided in `proposal` mode, and must be omitted in `template` mode.\nAll other fields are optional.", + "properties": { + "capabilities": { + "description": "A list of client-side supported capability features", + "items": { + "$ref": "#/components/schemas/GetBlockTemplateCapability" + }, + "type": "array" + }, + "data": { + "anyOf": [ + { + "$ref": "#/components/schemas/HexData" + }, + { + "type": "null" + } + ], + "description": "Must be omitted when `getblocktemplate` RPC is called in \"template\" mode (or when `mode` is omitted).\nMust be provided when `getblocktemplate` RPC is called in \"proposal\" mode.\n\nHex-encoded block data to be validated and checked against the server's usual acceptance rules\n(excluding the check for a valid proof-of-work)." + }, + "longpollid": { + "anyOf": [ + { + "$ref": "#/components/schemas/LongPollId" + }, + { + "type": "null" + } + ], + "description": "An ID that delays the RPC response until the template changes.\n\nIn Zebra, the ID represents the chain tip, max time, and mempool contents." + }, + "mode": { + "$ref": "#/components/schemas/GetBlockTemplateRequestMode", + "default": "template", + "description": "Defines whether the RPC method should generate a block template or attempt to\nvalidate block data, checking against all of the server's usual acceptance rules\n(excluding the check for a valid proof-of-work)." + }, + "workid": { + "description": "The workid for the block template.\n\ncurrently unused.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "GetBlockTemplateRequestMode": { + "description": "Defines whether the RPC method should generate a block template or attempt to validate a block\nproposal.", + "oneOf": [ + { + "const": "template", + "description": "Indicates a request for a block template.", + "type": "string" + }, + { + "const": "proposal", + "description": "Indicates a request to validate block data.", + "type": "string" + } + ] + }, + "GetNotesCount": { + "description": "The number of notes in the wallet.", + "properties": { + "orchard": { + "description": "The number of Orchard notes in the wallet.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "sapling": { + "description": "The number of Sapling notes in the wallet.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "sprout": { + "description": "The number of Sprout notes in the wallet.\n\nAlways zero, because Sprout is not supported.", + "format": "uint32", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "sprout", + "sapling", + "orchard" + ], + "type": "object" + }, + "GetWalletInfo": { + "description": "The wallet state information.", + "properties": { + "balance": { + "description": "The total confirmed transparent balance of the wallet in ZEC.", + "minimum": 0, + "type": "number" + }, + "immature_balance": { + "description": "The total immature transparent balance of the wallet in ZEC.", + "minimum": 0, + "type": "number" + }, + "keypoololdest": { + "description": "The timestamp (seconds since GMT epoch) of the oldest pre-generated key in the\nkey pool.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "keypoolsize": { + "description": "How many new keys are pre-generated.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "mnemonic_seedfp": { + "description": "The BLAKE2b-256 hash of the HD seed derived from the wallet's emergency recovery phrase.", + "type": "string" + }, + "shielded_balance": { + "description": "The total confirmed shielded balance of the wallet in ZEC.", + "type": "string" + }, + "shielded_unconfirmed_balance": { + "description": "The total unconfirmed shielded balance of the wallet in ZEC.\n\nNot included if `asOfHeight` is specified.", + "type": [ + "string", + "null" + ] + }, + "txcount": { + "description": "The total number of transactions in the wallet", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "unconfirmed_balance": { + "description": "The total unconfirmed transparent balance of the wallet in ZEC.\n\nNot included if `asOfHeight` is specified.", + "minimum": 0, + "type": [ + "number", + "null" + ] + }, + "unlocked_until": { + "description": "The timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is\nunlocked for transfers, or 0 if the wallet is locked.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "walletversion": { + "description": "The wallet version, in its \"Bitcoin client version\" form.", + "format": "uint64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "walletversion", + "balance", + "immature_balance", + "shielded_balance", + "txcount", + "keypoololdest", + "keypoolsize", + "mnemonic_seedfp" + ], + "type": "object" + }, + "HexData": { + "description": "Deserialize hex-encoded strings to bytes.", + "type": "string" + }, + "ListUnifiedReceivers": { + "description": "The receivers within a unified address.", + "properties": { + "orchard": { + "description": "A single-receiver Unified Address containing the Orchard receiver.", + "type": [ + "string", + "null" + ] + }, + "p2pkh": { + "description": "The legacy P2PKH transparent address.\n\nOmitted if `p2sh` is present.", + "type": [ + "string", + "null" + ] + }, + "p2sh": { + "description": "The legacy P2SH transparent address.\n\nOmitted if `p2pkh` is present.", + "type": [ + "string", + "null" + ] + }, + "sapling": { + "description": "The legacy Sapling address.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "LongPollId": { + "description": "The encoded long poll ID, generated from the [`LongPollInput`].\n\n`zcashd` IDs are currently 69 hex/decimal digits long.\nSince Zebra's IDs are only 46 hex/decimal digits, mining pools should be able to handle them.", + "type": "string" + }, + "NoteCommitmentSubtreeIndex": { + "description": "A note commitment subtree index, used to identify a subtree in a shielded pool.\nAlso used to count subtrees.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "OpenRPC Schema": { + "$ref": "https://raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json" + }, + "OperationError": { + "properties": { + "code": { + "description": "Code", + "format": "int32", + "type": "integer" + }, + "data": { + "description": "Optional data", + "type": [ + "string", + "null" + ] + }, + "message": { + "description": "Message", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" + }, + "OperationId": { + "description": "An async operation ID.", + "type": "string" + }, + "OperationState": { + "description": "The possible states that an async operation can be in.", + "enum": [ + "Ready", + "Executing", + "Cancelled", + "Failed", + "Success" + ], + "type": "string" + }, + "OperationStatus": { + "description": "The status of an async operation.", + "properties": { + "creation_time": { + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "error": { + "anyOf": [ + { + "$ref": "#/components/schemas/OperationError" + }, + { + "type": "null" + } + ] + }, + "execution_secs": { + "description": "Execution time for successful operations.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "id": { + "$ref": "#/components/schemas/OperationId" + }, + "method": { + "type": [ + "string", + "null" + ] + }, + "params": true, + "result": true, + "status": { + "$ref": "#/components/schemas/OperationState" + } + }, + "required": [ + "id", + "status", + "creation_time" + ], + "type": "object" + }, + "Orchard": { + "properties": { + "actions": { + "description": "The Orchard Actions for the transaction.", + "items": { + "$ref": "#/components/schemas/OrchardAction" + }, + "type": "array" + }, + "anchor": { + "description": "A root of the Orchard note commitment tree at some block height in the past,\nencoded as a hex string.\n\nOmitted if `actions` is empty.", + "type": [ + "string", + "null" + ] + }, + "bindingSig": { + "description": "An Orchard binding signature on the SIGHASH transaction hash, encoded as a hex\nstring.\n\nOmitted if `actions` is empty.", + "type": [ + "string", + "null" + ] + }, + "flags": { + "anyOf": [ + { + "$ref": "#/components/schemas/OrchardFlags" + }, + { + "type": "null" + } + ], + "description": "The Orchard bundle flags.\n\nOmitted if `actions` is empty." + }, + "proof": { + "description": "Encoding of aggregated zk-SNARK proofs for Orchard Actions, encoded as a hex\nstring.\n\nOmitted if `actions` is empty.", + "type": [ + "string", + "null" + ] + }, + "valueBalance": { + "description": "The net value of Orchard Actions in ZEC.", + "type": "number" + }, + "valueBalanceZat": { + "description": "The net value of Orchard Actions in zatoshis.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "actions", + "valueBalance", + "valueBalanceZat" + ], + "type": "object" + }, + "OrchardAction": { + "properties": { + "cmx": { + "description": "The x-coordinate of the note commitment for the output note, encoded as a hex\nstring.", + "type": "string" + }, + "cv": { + "description": "A value commitment to the net value of the input note minus the output note,\nencoded as a hex string.", + "type": "string" + }, + "encCiphertext": { + "description": "The output note encrypted to the recipient, encoded as a hex string.", + "type": "string" + }, + "ephemeralKey": { + "description": "An encoding of an ephemeral Pallas public key, encoded as a hex string.", + "type": "string" + }, + "nullifier": { + "description": "The nullifier of the input note, encoded as a hex string.", + "type": "string" + }, + "outCiphertext": { + "description": "A ciphertext enabling the sender to recover the output note, encoded as a hex\nstring.", + "type": "string" + }, + "rk": { + "description": "The randomized validating key for `spendAuthSig`, encoded as a hex string.", + "type": "string" + }, + "spendAuthSig": { + "description": "A signature authorizing the spend in this Action, encoded as a hex string.", + "type": "string" + } + }, + "required": [ + "cv", + "nullifier", + "rk", + "cmx", + "ephemeralKey", + "encCiphertext", + "outCiphertext", + "spendAuthSig" + ], + "type": "object" + }, + "OrchardFlags": { + "properties": { + "enableOutputs": { + "description": "Whether outputs are enabled in this Orchard bundle.", + "type": "boolean" + }, + "enableSpends": { + "description": "Whether spends are enabled in this Orchard bundle.", + "type": "boolean" + } + }, + "required": [ + "enableSpends", + "enableOutputs" + ], + "type": "object" + }, + "Output": { + "properties": { + "account_uuid": { + "description": "The UUID of the Zallet account that received the output.\n\nOmitted if the output is not for an account in the wallet (`outgoing = true`).", + "type": [ + "string", + "null" + ] + }, + "action": { + "description": "(orchard) the index of the action within the orchard bundle.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "address": { + "description": "The Zcash address that received the output.\n\nOmitted if this output was received on an account-internal address (e.g. change outputs),\nor is a transparent output to a script that is not either P2PKH or P2SH (and thus doesn't\nhave an address encoding).", + "type": [ + "string", + "null" + ] + }, + "memo": { + "description": "Hexadecimal string representation of the memo field.\n\nOmitted if this is a transparent output.", + "type": [ + "string", + "null" + ] + }, + "memoStr": { + "description": "UTF-8 string representation of memo field (if it contains valid UTF-8).\n\nOmitted if this is a transparent output.", + "type": [ + "string", + "null" + ] + }, + "outgoing": { + "description": "`true` if the output is not for an address in the wallet.", + "type": "boolean" + }, + "output": { + "description": "(sapling) the index of the output within the `vShieldedOutput`.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "pool": { + "description": "The value pool.\n\nOne of `[\"transparent\", \"sapling\", \"orchard\"]`.", + "type": "string" + }, + "tOut": { + "description": "(transparent) the index of the output within the `vout`.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "value": { + "description": "The value of the output in ZEC.", + "minimum": 0, + "type": "number" + }, + "valueZat": { + "description": "The value of the output in zatoshis.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "walletInternal": { + "description": "`true` if the output was received by the account's internal viewing key.\n\nThe `address` field is guaranteed be absent when this field is set to `true`, in which case\nit indicates that this may be a change output, an output of a wallet-internal shielding\ntransaction, an output of a wallet-internal cross-account transfer, or otherwise is the\nresult of some wallet-internal operation.", + "type": "boolean" + } + }, + "required": [ + "pool", + "outgoing", + "walletInternal", + "value", + "valueZat" + ], + "type": "object" + }, + "PeerSocketAddr": { + "description": "A thin wrapper for [`SocketAddr`] which hides peer IP addresses in logs and metrics.", + "type": "string" + }, + "ResultType": { + "description": "Empty result indicating success.", + "type": "null" + }, + "ResultType10": { + "anyOf": [ + { + "description": "The serialized, hex-encoded data for `txid`.", + "type": "string" + }, + { + "$ref": "#/components/schemas/Transaction2", + "description": "An object describing the transaction in detail." + } + ], + "description": "The `getrawtransaction` response." + }, + "ResultType11": { + "description": "A list of address sources.", + "items": { + "$ref": "#/components/schemas/AddressSource" + }, + "type": "array" + }, + "ResultType2": { + "description": "The help response.", + "type": "string" + }, + "ResultType3": { + "description": "The stop response.", + "type": "null" + }, + "ResultType4": { + "description": "The relevant operations.", + "items": { + "$ref": "#/components/schemas/OperationStatus" + }, + "type": "array" + }, + "ResultType5": { + "description": "Empty result indicating success.", + "type": "null" + }, + "ResultType6": { + "description": "A list of transactions involving the wallet.", + "items": { + "$ref": "#/components/schemas/WalletTx" + }, + "type": "array" + }, + "ResultType7": { + "description": "A list of accounts.", + "items": { + "$ref": "#/components/schemas/Account2" + }, + "type": "array" + }, + "ResultType8": { + "description": "A list of operation IDs.", + "items": { + "$ref": "#/components/schemas/OperationId" + }, + "type": "array" + }, + "ResultType9": { + "description": "A list of unspent notes.", + "items": { + "$ref": "#/components/schemas/UnspentOutput" + }, + "type": "array" + }, + "SaplingAddresses": { + "properties": { + "addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "zip32KeyPath": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "addresses" + ], + "type": "object" + }, + "SaplingOutput": { + "properties": { + "cmu": { + "description": "The u-coordinate of the note commitment for the output note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "cv": { + "description": "Value commitment to the output note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "encCiphertext": { + "description": "The output note encrypted to the recipient, encoded as a hex string.", + "type": "string" + }, + "ephemeralKey": { + "description": "A Jubjub public key.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "outCiphertext": { + "description": "A ciphertext enabling the sender to recover the output note, encoded as a hex\nstring.", + "type": "string" + }, + "proof": { + "description": "A zero-knowledge proof using the Sapling Output circuit, encoded as a hex string.", + "type": "string" + } + }, + "required": [ + "cv", + "cmu", + "ephemeralKey", + "encCiphertext", + "outCiphertext", + "proof" + ], + "type": "object" + }, + "SaplingSpend": { + "properties": { + "anchor": { + "description": "Merkle root of the Sapling note commitment tree.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "cv": { + "description": "Value commitment to the input note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "nullifier": { + "description": "The nullifier of the input note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "proof": { + "description": "A zero-knowledge proof using the Sapling Spend circuit, encoded as a hex string.", + "type": "string" + }, + "rk": { + "description": "The randomized public key for `spendAuthSig`.\n\nEncoded as a byte-reversed hex string for legacy reasons.", + "type": "string" + }, + "spendAuthSig": { + "description": "A signature authorizing this Spend, encoded as a hex string.", + "type": "string" + } + }, + "required": [ + "cv", + "anchor", + "nullifier", + "rk", + "proof", + "spendAuthSig" + ], + "type": "object" + }, + "Spend": { + "properties": { + "account_uuid": { + "description": "The UUID of the Zallet account that received the corresponding output.\n\nOmitted if the output is not for an account in the wallet (which always means that\n`pool` is `\"transparent\"`; external shielded spends are never included because\nthey are unviewable).", + "type": [ + "string", + "null" + ] + }, + "action": { + "description": "(orchard) the index of the action within orchard bundle.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "actionPrev": { + "description": "(orchard) the index of the corresponding action within the previous transaction's\nOrchard bundle.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "address": { + "description": "The Zcash address involved in the transaction.\n\nOmitted if this note was received on an account-internal address (e.g. change\nnotes).", + "type": [ + "string", + "null" + ] + }, + "outputPrev": { + "description": "(sapling) the index of the corresponding output within the previous transaction's\n`vShieldedOutput`.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "pool": { + "description": "The value pool.\n\nOne of `[\"transparent\", \"sapling\", \"orchard\"]`.", + "type": "string" + }, + "spend": { + "description": "(sapling) the index of the spend within `vShieldedSpend`.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "tIn": { + "description": "(transparent) the index of the spend within `vin`.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "tOutPrev": { + "description": "(transparent) the index of the corresponding output within the previous\ntransaction's `vout`.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "txidPrev": { + "description": "The id for the transaction this note was created in.", + "type": "string" + }, + "value": { + "description": "The amount in ZEC.", + "minimum": 0, + "type": "number" + }, + "valueZat": { + "description": "The amount in zatoshis.", + "format": "uint64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "pool", + "txidPrev", + "value", + "valueZat" + ], + "type": "object" + }, + "SubmitBlockParameters": { + "description": "Optional argument `jsonparametersobject` for `submitblock` RPC request\n\nSee the notes for the [`submit_block`](crate::methods::RpcServer::submit_block) RPC.", + "properties": { + "workid": { + "description": "The workid for the block template. Currently unused.\n\n> If the server provided a workid, it MUST be included with submissions,\n\nRationale:\n\n> If servers allow all mutations, it may be hard to identify which job it is based on.\n> While it may be possible to verify the submission by its content, it is much easier\n> to compare it to the job issued. It is very easy for the miner to keep track of this.\n> Therefore, using a \"workid\" is a very cheap solution to enable more mutations.\n\n", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "TotalBalance": { + "description": "The total value of funds stored in the wallet.", + "properties": { + "private": { + "description": "The total value of unspent Sapling and Orchard outputs, in ZEC", + "type": "string" + }, + "total": { + "description": "The total value of unspent shielded and transparent outputs, in ZEC", + "type": "string" + }, + "transparent": { + "description": "The total value of unspent transparent outputs, in ZEC", + "type": "string" + } + }, + "required": [ + "transparent", + "private", + "total" + ], + "type": "object" + }, + "Transaction": { + "description": "Detailed information about an in-wallet transaction.", + "properties": { + "accounts": { + "additionalProperties": { + "$ref": "#/components/schemas/AccountEffect" + }, + "description": "A map from an involved account's UUID to the effects of this transaction on it.", + "type": "object" + }, + "blockhash": { + "description": "The hash of the main chain block that this transaction is mined in.\n\nOmitted if this transaction is not mined within a block in the current best chain.", + "type": [ + "string", + "null" + ] + }, + "blockindex": { + "description": "The index of the transaction within its block's `vtx` field.\n\nOmitted if this transaction is not mined within a block in the current best chain.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "blocktime": { + "description": "The time in seconds since epoch (1 Jan 1970 GMT) that the main chain block\ncontaining this transaction was mined.\n\nOmitted if this transaction is not mined within a block in the current best chain.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "confirmations": { + "description": "The number of confirmations.\n\n- A positive value is the number of blocks that have been mined including the\n transaction in the chain. For example, 1 confirmation means the transaction is\n in the block currently at the chain tip.\n- 0 means the transaction is in the mempool. If `asOfHeight` was set, this case\n will not occur.\n- -1 means the transaction cannot be mined.", + "format": "int64", + "type": "integer" + }, + "expiryheight": { + "description": "The greatest height at which this transaction can be mined, or 0 if this\ntransaction does not expire.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "fee": { + "description": "The fee paid by the transaction.\n\nOmitted if this is a coinbase transaction, or if the fee cannot be determined\nbecause one or more transparent inputs of the transaction cannot be found.", + "minimum": 0, + "type": [ + "number", + "null" + ] + }, + "generated": { + "description": "Set to `true` if this is a coinbase transaction, omitted otherwise.", + "type": [ + "boolean", + "null" + ] + }, + "outputs": { + "description": "The outputs of the transaction that the wallet is capable of viewing.", + "items": { + "$ref": "#/components/schemas/Output" + }, + "type": "array" + }, + "spends": { + "description": "The inputs to the transaction that the wallet is capable of viewing.", + "items": { + "$ref": "#/components/schemas/Spend" + }, + "type": "array" + }, + "status": { + "description": "The transaction status.\n\nOne of 'mined', 'waiting', 'expiringsoon' or 'expired'.", + "type": "string" + }, + "txid": { + "description": "The transaction ID.", + "type": "string" + }, + "version": { + "description": "The transaction version.", + "format": "uint32", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "txid", + "status", + "confirmations", + "version", + "expiryheight", + "spends", + "outputs", + "accounts" + ], + "type": "object" + }, + "Transaction2": { + "description": "Verbose information about a transaction.", + "properties": { + "authdigest": { + "description": "The transaction's authorizing data commitment.\n\nFor pre-v5 transactions this will be `ffff..ffff`.\n\nEncoded as a byte-reversed hex string to match `txid`.", + "type": "string" + }, + "bindingSig": { + "description": "The Sapling binding signature, encoded as a hex string.\n\nOmitted if `version < 4`, or both `vShieldedSpend` and `vShieldedOutput` are empty.", + "type": [ + "string", + "null" + ] + }, + "blockhash": { + "description": "The hash of the block that the transaction is mined in, if any.\n\nOmitted if the transaction is not known to be mined in any block.", + "type": [ + "string", + "null" + ] + }, + "blocktime": { + "description": "The block time in seconds since epoch (Jan 1 1970 GMT) for the block that the\ntransaction is mined in.\n\nOmitted if `blockhash` is either omitted or not in the current best chain.", + "format": "int64", + "type": [ + "integer", + "null" + ] + }, + "confirmations": { + "description": "The number of confirmations the transaction has, or 0 if the block it is mined in\nis not in the current best chain.\n\nOmitted if `blockhash` is either omitted or unknown.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "expiryheight": { + "description": "The block height after which the transaction expires.\n\nOmitted if `overwintered` is `false`.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "height": { + "description": "The height of the block that the transaction is mined in, or -1 if that block is\nnot in the current best chain.\n\nOmitted if `blockhash` is either omitted or unknown.", + "format": "int32", + "type": [ + "integer", + "null" + ] + }, + "hex": { + "description": "The serialized, hex-encoded data for the transaction identified by `txid`.", + "type": "string" + }, + "in_active_chain": { + "description": "Whether specified block is in the active chain or not.\n\nOnly present with explicit `blockhash` argument.", + "type": [ + "boolean", + "null" + ] + }, + "locktime": { + "description": "The lock time.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "orchard": { + "anyOf": [ + { + "$ref": "#/components/schemas/Orchard" + }, + { + "type": "null" + } + ], + "description": "JSON object with Orchard-specific information.\n\nOmitted if `version < 5`." + }, + "overwintered": { + "description": "Whether the `overwintered` flag is set.", + "type": "boolean" + }, + "size": { + "description": "The network-serialized transaction size.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "time": { + "description": "The transaction time in seconds since epoch (Jan 1 1970 GMT).\n\nThis is always identical to `blocktime`.\n\nOmitted if `blockhash` is either omitted or not in the current best chain.", + "format": "int64", + "type": [ + "integer", + "null" + ] + }, + "txid": { + "description": "The transaction ID (same as provided).", + "type": "string" + }, + "vShieldedOutput": { + "description": "Omitted if `version < 4`.", + "items": { + "$ref": "#/components/schemas/SaplingOutput" + }, + "type": [ + "array", + "null" + ] + }, + "vShieldedSpend": { + "description": "Omitted if `version < 4`.", + "items": { + "$ref": "#/components/schemas/SaplingSpend" + }, + "type": [ + "array", + "null" + ] + }, + "valueBalance": { + "description": "The net value of Sapling Spends minus Outputs in ZEC.\n\nOmitted if `version < 4`.", + "type": [ + "number", + "null" + ] + }, + "valueBalanceZat": { + "description": "The net value of Sapling Spends minus Outputs in zatoshis.\n\nOmitted if `version < 4`.", + "format": "int64", + "type": [ + "integer", + "null" + ] + }, + "version": { + "description": "The transaction version.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "versiongroupid": { + "description": "The version group ID.\n\nOmitted if `overwintered` is `false`.", + "type": [ + "string", + "null" + ] + }, + "vin": { + "description": "The transparent inputs to the transaction.", + "items": { + "$ref": "#/components/schemas/TransparentInput" + }, + "type": "array" + }, + "vout": { + "description": "The transparent outputs from the transaction.", + "items": { + "$ref": "#/components/schemas/TransparentOutput" + }, + "type": "array" + } + }, + "required": [ + "hex", + "txid", + "authdigest", + "size", + "overwintered", + "version", + "locktime", + "vin", + "vout" + ], + "type": "object" + }, + "TransparentAddresses": { + "properties": { + "addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "changeAddresses": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "addresses", + "changeAddresses" + ], + "type": "object" + }, + "TransparentInput": { + "properties": { + "coinbase": { + "description": "The coinbase `scriptSig`, encoded as a hex string.\n\nOmitted if this is not a coinbase transaction.", + "type": [ + "string", + "null" + ] + }, + "scriptSig": { + "anyOf": [ + { + "$ref": "#/components/schemas/TransparentScriptSig" + }, + { + "type": "null" + } + ], + "description": "Omitted if this is a coinbase transaction." + }, + "sequence": { + "description": "The script sequence number.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "txid": { + "description": "The transaction ID of the output being spent.\n\nOmitted if this is a coinbase transaction.", + "type": [ + "string", + "null" + ] + }, + "vout": { + "description": "The index of the output being spent within the transaction identified by `txid`.\n\nOmitted if this is a coinbase transaction.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "required": [ + "sequence" + ], + "type": "object" + }, + "TransparentOutput": { + "properties": { + "n": { + "description": "The index of the output within the transaction's `vout` field.", + "format": "uint16", + "maximum": 65535, + "minimum": 0, + "type": "integer" + }, + "scriptPubKey": { + "$ref": "#/components/schemas/TransparentScriptPubKey" + }, + "value": { + "description": "The value in ZEC.", + "minimum": 0, + "type": "number" + }, + "valueSat": { + "description": "The value in zatoshis.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "valueZat": { + "description": "The value in zatoshis.", + "format": "uint64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "value", + "valueZat", + "valueSat", + "n", + "scriptPubKey" + ], + "type": "object" + }, + "TransparentScriptPubKey": { + "properties": { + "addresses": { + "description": "Array of the transparent P2PKH addresses involved in the script.", + "items": { + "type": "string" + }, + "type": "array" + }, + "asm": { + "description": "The assembly string representation of the script.", + "type": "string" + }, + "hex": { + "description": "The serialized script, encoded as a hex string.", + "type": "string" + }, + "reqSigs": { + "description": "The required number of signatures to spend this output.", + "format": "uint8", + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "type": { + "description": "The type of script.\n\nOne of `[\"pubkey\", \"pubkeyhash\", \"scripthash\", \"multisig\", \"nulldata\", \"nonstandard\"]`.", + "type": "string" + } + }, + "required": [ + "asm", + "hex", + "reqSigs", + "type", + "addresses" + ], + "type": "object" + }, + "TransparentScriptSig": { + "properties": { + "asm": { + "description": "The assembly string representation of the script.", + "type": "string" + }, + "hex": { + "description": "The serialized script, encoded as a hex string.", + "type": "string" + } + }, + "required": [ + "asm", + "hex" + ], + "type": "object" + }, + "UnifiedAddress": { + "properties": { + "address": { + "description": "The unified address corresponding to the diversifier.", + "type": "string" + }, + "diversifier_index": { + "description": "The diversifier index that the UA was derived at.", + "format": "uint128", + "minimum": 0, + "type": "integer" + }, + "receiver_types": { + "description": "The receiver types that the UA contains (valid values are \"p2pkh\", \"sapling\", \"orchard\").", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "diversifier_index", + "receiver_types", + "address" + ], + "type": "object" + }, + "UnifiedAddresses": { + "properties": { + "account": { + "description": "The ZIP 32 account index.", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "addresses": { + "items": { + "$ref": "#/components/schemas/UnifiedAddress" + }, + "type": "array" + }, + "seedfp": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "addresses" + ], + "type": "object" + }, + "UnspentOutput": { + "properties": { + "account_uuid": { + "description": "The UUID of the wallet account that received this output.", + "type": "string" + }, + "address": { + "description": "The Zcash address that received the output.\n\nOmitted if this output was received on an account-internal address (for example, change\nand shielding outputs).", + "type": [ + "string", + "null" + ] + }, + "confirmations": { + "description": "The number of confirmations.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "is_watch_only": { + "description": "`true` if the account that received the output is watch-only", + "type": "boolean" + }, + "memo": { + "description": "Hexadecimal string representation of the memo field.\n\nOmitted if this is a transparent output.", + "type": [ + "string", + "null" + ] + }, + "memoStr": { + "description": "UTF-8 string representation of memo field (if it contains valid UTF-8).", + "type": [ + "string", + "null" + ] + }, + "outindex": { + "description": "The Transparent UTXO, Sapling output or Orchard action index.", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "pool": { + "description": "The shielded value pool.\n\nOne of `[\"sapling\", \"orchard\", \"transparent\"]`.", + "type": "string" + }, + "txid": { + "description": "The ID of the transaction that created this output.", + "type": "string" + }, + "value": { + "description": "The value of the output in ZEC.", + "minimum": 0, + "type": "number" + }, + "valueZat": { + "description": "The value of the output in zatoshis.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "walletInternal": { + "description": "`true` if the output was received by the account's internal viewing key.\n\nThe `address` field is guaranteed be absent when this field is set to `true`, in which case\nit indicates that this may be a change output, an output of a wallet-internal shielding\ntransaction, an output of a wallet-internal cross-account transfer, or otherwise is the\nresult of some wallet-internal operation.", + "type": "boolean" + } + }, + "required": [ + "txid", + "pool", + "outindex", + "confirmations", + "is_watch_only", + "account_uuid", + "walletInternal", + "value", + "valueZat" + ], + "type": "object" + }, + "WalletTx": { + "description": "A transaction that affects an account in a wallet.", + "properties": { + "account_balance_delta": { + "description": "The delta to the account produced by the transaction", + "format": "int64", + "type": "integer" + }, + "account_uuid": { + "description": "The UUID of the account that this transaction entry is acting on.\n\nA transaction that has effects on multiple accounts will have multiple rows in the result.", + "type": "string" + }, + "block_datetime": { + "description": "The human-readable datetime at which the block was mined.", + "type": [ + "string", + "null" + ] + }, + "block_time": { + "description": "The timestamp at which the block was mined.", + "format": "int64", + "type": [ + "integer", + "null" + ] + }, + "expired_unmined": { + "description": "Whether or not the transaction expired without having been mined.", + "type": "boolean" + }, + "expiry_height": { + "description": "The expiry height of the transaction", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "fee_paid": { + "description": "The fee paid by the transaction, if known.", + "format": "uint64", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "mined_height": { + "description": "The height at which the transaction was mined", + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "outputs": { + "description": "The outputs of the transaction received by the wallet.", + "items": { + "$ref": "#/components/schemas/WalletTxOutput" + }, + "type": "array" + }, + "received_note_count": { + "description": "The number of outputs received by the transaction.", + "format": "uint", + "minimum": 0, + "type": "integer" + }, + "sent_note_count": { + "description": "The number of outputs produced by the transaction.", + "format": "uint", + "minimum": 0, + "type": "integer" + }, + "txid": { + "description": "The transaction identifier", + "type": "string" + } + }, + "required": [ + "account_uuid", + "txid", + "account_balance_delta", + "sent_note_count", + "received_note_count", + "expired_unmined", + "outputs" + ], + "type": "object" + }, + "WalletTxOutput": { + "description": "Basic information about a transaction output that was either created or received by this\nwallet.", + "properties": { + "from_account": { + "type": [ + "string", + "null" + ] + }, + "is_change": { + "type": "boolean" + }, + "memo": { + "type": [ + "string", + "null" + ] + }, + "output_index": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "pool": { + "type": "string" + }, + "to_account": { + "type": [ + "string", + "null" + ] + }, + "to_address": { + "type": [ + "string", + "null" + ] + }, + "value": { + "format": "uint64", + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "pool", + "output_index", + "value", + "is_change" + ], + "type": "object" + } + } + }, + "info": { + "description": "Z3 RPC request router", + "title": "rpc-router", + "version": "0.1.0" + }, + "methods": [ + { + "description": "Returns all transaction ids in the memory pool, as a JSON array.\n\n# Parameters\n\n- `verbose`: (boolean, optional, default=false) true for a json object, false for array of transaction ids.\n\nzcashd reference: [`getrawmempool`](https://zcash.github.io/rpc/getrawmempool.html)\nmethod: post\ntags: blockchain", + "name": "getrawmempool", + "params": [ + { + "description": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data.", + "name": "verbose", + "schema": { + "type": "boolean" + }, + "summary": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getrawmempool_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns all transaction ids in the memory pool, as a JSON array.", + "x-server": "zebra" + }, + { + "description": "Returns information about a range of Sapling or Orchard subtrees.\n\nzcashd reference: [`z_getsubtreesbyindex`](https://zcash.github.io/rpc/z_getsubtreesbyindex.html) - TODO: fix link\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `pool`: (string, required) The pool from which subtrees should be returned. Either \"sapling\" or \"orchard\".\n- `start_index`: (number, required) The index of the first 2^16-leaf subtree to return.\n- `limit`: (number, optional) The maximum number of subtree values to return.\n\n# Notes\n\nWhile Zebra is doing its initial subtree index rebuild, subtrees will become available\nstarting at the chain tip. This RPC will return an empty list if the `start_index` subtree\nexists, but has not been rebuilt yet. This matches `zcashd`'s behaviour when subtrees aren't\navailable yet. (But `zcashd` does its rebuild before syncing any blocks.)", + "name": "z_getsubtreesbyindex", + "params": [ + { + "description": "The pool from which subtrees should be returned. Either \"sapling\" or \"orchard\".", + "name": "pool", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The pool from which subtrees should be returned. Either \"sapling\" or \"orchard\"." + }, + { + "description": "The index of the first 2^16-leaf subtree to return.", + "name": "start_index", + "required": true, + "schema": { + "$ref": "#/components/schemas/NoteCommitmentSubtreeIndex" + }, + "summary": "The index of the first 2^16-leaf subtree to return." + }, + { + "description": "The maximum number of subtrees to return.", + "name": "limit", + "schema": { + "$ref": "#/components/schemas/NoteCommitmentSubtreeIndex" + }, + "summary": "The maximum number of subtrees to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "z_getsubtreesbyindex_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns information about a range of Sapling or Orchard subtrees.", + "x-server": "zebra" + }, + { + "description": "Returns the hash of the current best blockchain tip block, as a [`GetBlockHash`] JSON string.\n\nzcashd reference: [`getbestblockhash`](https://zcash.github.io/rpc/getbestblockhash.html)\nmethod: post\ntags: blockchain", + "name": "getbestblockhash", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getbestblockhash_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the hash of the current best blockchain tip block, as a [`GetBlockHash`] JSON string.", + "x-server": "zebra" + }, + { + "description": "Stop the running zebrad process.\n\n# Notes\n\n- Works for non windows targets only.\n- Works only if the network of the running zebrad process is `Regtest`.\n\nzcashd reference: [`stop`](https://zcash.github.io/rpc/stop.html)\nmethod: post\ntags: control", + "name": "stop", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "stop_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Stop the running zebrad process.", + "x-server": "zebra" + }, + { + "description": "Returns the transaction ids made by the provided transparent addresses.\n\nzcashd reference: [`getaddresstxids`](https://zcash.github.io/rpc/getaddresstxids.html)\nmethod: post\ntags: address\n\n# Parameters\n\n- `request`: (required) Either:\n - A single address string (e.g., `\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"`), or\n - An object with the following named fields:\n - `addresses`: (array of strings, required) The addresses to get transactions from.\n - `start`: (numeric, optional) The lower height to start looking for transactions (inclusive).\n - `end`: (numeric, optional) The upper height to stop looking for transactions (inclusive).\n\nExample of the object form:\n```json\n{\n \"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"],\n \"start\": 1000,\n \"end\": 2000\n}\n```\n\n# Notes\n\n- Only the multi-argument format is used by lightwalletd and this is what we currently support:\n\n- It is recommended that users call the method with start/end heights such that the response can't be too large.", + "name": "getaddresstxids", + "params": [ + { + "description": "The request object containing the parameters.", + "name": "request", + "required": true, + "schema": { + "$ref": "#/components/schemas/GetAddressTxIdsRequest" + }, + "summary": "The request object containing the parameters." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getaddresstxids_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the transaction ids made by the provided transparent addresses.", + "x-server": "zebra" + }, + { + "description": "Returns the hash of the block of a given height iff the index argument correspond\nto a block in the best chain.\n\nzcashd reference: [`getblockhash`](https://zcash-rpc.github.io/getblockhash.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `index`: (numeric, required, example=1) The block index.\n\n# Notes\n\n- If `index` is positive then index = block height.\n- If `index` is negative then -1 is the last known valid block.", + "name": "getblockhash", + "params": [ + { + "description": "The index of the subtree to return.", + "name": "index", + "required": true, + "schema": { + "format": "int32", + "type": "integer" + }, + "summary": "The index of the subtree to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getblockhash_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the hash of the block of a given height iff the index argument correspond", + "x-server": "zebra" + }, + { + "description": "Sends the raw bytes of a signed transaction to the local node's mempool, if the transaction is valid.\nReturns the [`SentTransactionHash`] for the transaction, as a JSON string.\n\nzcashd reference: [`sendrawtransaction`](https://zcash.github.io/rpc/sendrawtransaction.html)\nmethod: post\ntags: transaction\n\n# Parameters\n\n- `raw_transaction_hex`: (string, required, example=\"signedhex\") The hex-encoded raw transaction bytes.\n- `allow_high_fees`: (bool, optional) A legacy parameter accepted by zcashd but ignored by Zebra.\n\n# Notes\n\nzcashd accepts an optional `allowhighfees` parameter. Zebra doesn't support this parameter,\nbecause lightwalletd doesn't use it.", + "name": "sendrawtransaction", + "params": [ + { + "description": "The hex-encoded raw transaction bytes.", + "name": "raw_transaction_hex", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The hex-encoded raw transaction bytes." + }, + { + "description": "Whether to allow high fees.", + "name": "_allow_high_fees", + "schema": { + "type": "boolean" + }, + "summary": "Whether to allow high fees." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "sendrawtransaction_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Sends the raw bytes of a signed transaction to the local node's mempool, if the transaction is valid.", + "x-server": "zebra" + }, + { + "description": "Returns the estimated network solutions per second based on the last `num_blocks` before\n`height`.\n\nIf `num_blocks` is not supplied, uses 120 blocks. If it is 0 or -1, uses the difficulty\naveraging window.\nIf `height` is not supplied or is -1, uses the tip height.\n\nzcashd reference: [`getnetworksolps`](https://zcash.github.io/rpc/getnetworksolps.html)\nmethod: post\ntags: mining", + "name": "getnetworksolps", + "params": [ + { + "description": "The number of blocks to return.", + "name": "num_blocks", + "schema": { + "format": "int32", + "type": "integer" + }, + "summary": "The number of blocks to return." + }, + { + "description": "The height of the block to return.", + "name": "height", + "schema": { + "format": "int32", + "type": "integer" + }, + "summary": "The height of the block to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getnetworksolps_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the estimated network solutions per second based on the last `num_blocks` before", + "x-server": "zebra" + }, + { + "description": "Returns an OpenRPC schema as a description of this service.", + "name": "rpc.discover", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "rpc.discover_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns an OpenRPC schema as a description of this service.", + "x-server": "zebra" + }, + { + "description": "Returns mining-related information.\n\nzcashd reference: [`getmininginfo`](https://zcash.github.io/rpc/getmininginfo.html)\nmethod: post\ntags: mining", + "name": "getmininginfo", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getmininginfo_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns mining-related information.", + "x-server": "zebra" + }, + { + "description": "Add or remove a node from the address book.\n\n# Parameters\n\n- `addr`: (string, required) The address of the node to add or remove.\n- `command`: (string, required) The command to execute, either \"add\", \"onetry\", or \"remove\".\n\n# Notes\n\nOnly the \"add\" command is currently supported.\n\nzcashd reference: [`addnode`](https://zcash.github.io/rpc/addnode.html)\nmethod: post\ntags: network", + "name": "addnode", + "params": [ + { + "description": "The address to return.", + "name": "addr", + "required": true, + "schema": { + "$ref": "#/components/schemas/PeerSocketAddr" + }, + "summary": "The address to return." + }, + { + "description": "The command to execute.", + "name": "command", + "required": true, + "schema": { + "$ref": "#/components/schemas/AddNodeCommand" + }, + "summary": "The command to execute." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "addnode_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Add or remove a node from the address book.", + "x-server": "zebra" + }, + { + "description": "Submits block to the node to be validated and committed.\nReturns the [`SubmitBlockResponse`] for the operation, as a JSON string.\n\nzcashd reference: [`submitblock`](https://zcash.github.io/rpc/submitblock.html)\nmethod: post\ntags: mining\n\n# Parameters\n\n- `hexdata`: (string, required)\n- `jsonparametersobject`: (string, optional) - currently ignored\n\n# Notes\n\n - `jsonparametersobject` holds a single field, workid, that must be included in submissions if provided by the server.", + "name": "submitblock", + "params": [ + { + "description": "The hex-encoded data to return.", + "name": "hex_data", + "required": true, + "schema": { + "$ref": "#/components/schemas/HexData" + }, + "summary": "The hex-encoded data to return." + }, + { + "description": "The parameters for the command.", + "name": "_parameters", + "schema": { + "$ref": "#/components/schemas/SubmitBlockParameters" + }, + "summary": "The parameters for the command." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "submitblock_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Submits block to the node to be validated and committed.", + "x-server": "zebra" + }, + { + "description": "Reconsiders a previously invalidated block if it exists in the cache of previously invalidated blocks.\n\n# Parameters\n\n- `block_hash`: (hex-encoded block hash, required) The block hash to reconsider.", + "name": "reconsiderblock", + "params": [ + { + "description": "The hash of the block to return.", + "name": "block_hash", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The hash of the block to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "reconsiderblock_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Reconsiders a previously invalidated block if it exists in the cache of previously invalidated blocks.", + "x-server": "zebra" + }, + { + "description": "Checks if a zcash transparent address of type P2PKH, P2SH or TEX is valid.\nReturns information about the given address if valid.\n\nzcashd reference: [`validateaddress`](https://zcash.github.io/rpc/validateaddress.html)\nmethod: post\ntags: util\n\n# Parameters\n\n- `address`: (string, required) The zcash address to validate.", + "name": "validateaddress", + "params": [ + { + "description": "The address to return.", + "name": "address", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The address to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "validateaddress_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Checks if a zcash transparent address of type P2PKH, P2SH or TEX is valid.", + "x-server": "zebra" + }, + { + "description": "Returns the height and hash of the current best blockchain tip block, as a [`GetBlockHeightAndHashResponse`] JSON struct.\n\nzcashd reference: none\nmethod: post\ntags: blockchain", + "name": "getbestblockheightandhash", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getbestblockheightandhash_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the height and hash of the current best blockchain tip block, as a [`GetBlockHeightAndHashResponse`] JSON struct.", + "x-server": "zebra" + }, + { + "description": "Returns the height of the most recent block in the best valid block chain (equivalently,\nthe number of blocks in this chain excluding the genesis block).\n\nzcashd reference: [`getblockcount`](https://zcash.github.io/rpc/getblockcount.html)\nmethod: post\ntags: blockchain", + "name": "getblockcount", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getblockcount_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the height of the most recent block in the best valid block chain (equivalently,", + "x-server": "zebra" + }, + { + "description": "Returns the total balance of a provided `addresses` in an [`AddressBalance`] instance.\n\nzcashd reference: [`getaddressbalance`](https://zcash.github.io/rpc/getaddressbalance.html)\nmethod: post\ntags: address\n\n# Parameters\n\n- `address_strings`: (object, example={\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}) A JSON map with a single entry\n - `addresses`: (array of strings) A list of base-58 encoded addresses.\n\n# Notes\n\nzcashd also accepts a single string parameter instead of an array of strings, but Zebra\ndoesn't because lightwalletd always calls this RPC with an array of addresses.\n\nzcashd also returns the total amount of Zatoshis received by the addresses, but Zebra\ndoesn't because lightwalletd doesn't use that information.\n\nThe RPC documentation says that the returned object has a string `balance` field, but\nzcashd actually [returns an\ninteger](https://github.com/zcash/lightwalletd/blob/bdaac63f3ee0dbef62bde04f6817a9f90d483b00/common/common.go#L128-L130).", + "name": "getaddressbalance", + "params": [ + { + "description": "The addresses to return.", + "name": "address_strings", + "required": true, + "schema": { + "$ref": "#/components/schemas/GetAddressBalanceRequest" + }, + "summary": "The addresses to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getaddressbalance_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the total balance of a provided `addresses` in an [`AddressBalance`] instance.", + "x-server": "zebra" + }, + { + "description": "Returns software information from the RPC server, as a [`GetInfo`] JSON struct.\n\nzcashd reference: [`getinfo`](https://zcash.github.io/rpc/getinfo.html)\nmethod: post\ntags: control\n\n# Notes\n\n[The zcashd reference](https://zcash.github.io/rpc/getinfo.html) might not show some fields\nin Zebra's [`GetInfo`]. Zebra uses the field names and formats from the\n[zcashd code](https://github.com/zcash/zcash/blob/v4.6.0-1/src/rpc/misc.cpp#L86-L87).\n\nSome fields from the zcashd reference are missing from Zebra's [`GetInfo`]. It only contains the fields\n[required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L91-L95)", + "name": "getinfo", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getinfo_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns software information from the RPC server, as a [`GetInfo`] JSON struct.", + "x-server": "zebra" + }, + { + "description": "Mine blocks immediately. Returns the block hashes of the generated blocks.\n\n# Parameters\n\n- `num_blocks`: (numeric, required, example=1) Number of blocks to be generated.\n\n# Notes\n\nOnly works if the network of the running zebrad process is `Regtest`.\n\nzcashd reference: [`generate`](https://zcash.github.io/rpc/generate.html)\nmethod: post\ntags: generating", + "name": "generate", + "params": [ + { + "description": "The number of blocks to return.", + "name": "num_blocks", + "required": true, + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "The number of blocks to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "generate_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Mine blocks immediately. Returns the block hashes of the generated blocks.", + "x-server": "zebra" + }, + { + "description": "Returns the estimated network solutions per second based on the last `num_blocks` before\n`height`.\n\nThis method name is deprecated, use [`getnetworksolps`](Self::get_network_sol_ps) instead.\nSee that method for details.\n\nzcashd reference: [`getnetworkhashps`](https://zcash.github.io/rpc/getnetworkhashps.html)\nmethod: post\ntags: mining", + "name": "getnetworkhashps", + "params": [ + { + "description": "The number of blocks to return.", + "name": "num_blocks", + "schema": { + "format": "int32", + "type": "integer" + }, + "summary": "The number of blocks to return." + }, + { + "description": "The height of the block to return.", + "name": "height", + "schema": { + "format": "int32", + "type": "integer" + }, + "summary": "The height of the block to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getnetworkhashps_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the estimated network solutions per second based on the last `num_blocks` before", + "x-server": "zebra" + }, + { + "description": "Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct.\n\nzcashd reference: [`getblockchaininfo`](https://zcash.github.io/rpc/getblockchaininfo.html)\nmethod: post\ntags: blockchain\n\n# Notes\n\nSome fields from the zcashd reference are missing from Zebra's [`GetBlockchainInfoResponse`]. It only contains the fields\n[required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89)", + "name": "getblockchaininfo", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getblockchaininfo_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct.", + "x-server": "zebra" + }, + { + "description": "Returns all unspent outputs for a list of addresses.\n\nzcashd reference: [`getaddressutxos`](https://zcash.github.io/rpc/getaddressutxos.html)\nmethod: post\ntags: address\n\n# Parameters\n\n- `request`: (required) Either:\n - A single address string (e.g., `\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"`), or\n - An object with the following named fields:\n - `addresses`: (array, required, example=[\\\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\\\"]) The addresses to get outputs from.\n - `chaininfo`: (boolean, optional, default=false) Include chain info with results\n\n# Notes\n\nlightwalletd always uses the multi-address request, without chaininfo:\n", + "name": "getaddressutxos", + "params": [ + { + "description": "The request object containing the parameters.", + "name": "request", + "required": true, + "schema": { + "$ref": "#/components/schemas/GetAddressUtxosRequest" + }, + "summary": "The request object containing the parameters." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getaddressutxos_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns all unspent outputs for a list of addresses.", + "x-server": "zebra" + }, + { + "description": "Invalidates a block if it is not yet finalized, removing it from the non-finalized\nstate if it is present and rejecting it during contextual validation if it is submitted.\n\n# Parameters\n\n- `block_hash`: (hex-encoded block hash, required) The block hash to invalidate.", + "name": "invalidateblock", + "params": [ + { + "description": "The hash of the block to return.", + "name": "block_hash", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The hash of the block to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "invalidateblock_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Invalidates a block if it is not yet finalized, removing it from the non-finalized", + "x-server": "zebra" + }, + { + "description": "Returns the block subsidy reward of the block at `height`, taking into account the mining slow start.\nReturns an error if `height` is less than the height of the first halving for the current network.\n\nzcashd reference: [`getblocksubsidy`](https://zcash.github.io/rpc/getblocksubsidy.html)\nmethod: post\ntags: mining\n\n# Parameters\n\n- `height`: (numeric, optional, example=1) Can be any valid current or future height.\n\n# Notes\n\nIf `height` is not supplied, uses the tip height.", + "name": "getblocksubsidy", + "params": [ + { + "description": "The height of the block to return.", + "name": "height", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "The height of the block to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getblocksubsidy_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the block subsidy reward of the block at `height`, taking into account the mining slow start.", + "x-server": "zebra" + }, + { + "description": "Returns the raw transaction data, as a [`GetRawTransaction`] JSON string or structure.\n\nzcashd reference: [`getrawtransaction`](https://zcash.github.io/rpc/getrawtransaction.html)\nmethod: post\ntags: transaction\n\n# Parameters\n\n- `txid`: (string, required, example=\"mytxid\") The transaction ID of the transaction to be returned.\n- `verbose`: (number, optional, default=0, example=1) If 0, return a string of hex-encoded data, otherwise return a JSON object.\n- `blockhash` (string, optional) The block in which to look for the transaction", + "name": "getrawtransaction", + "params": [ + { + "description": "The transaction ID to return.", + "name": "txid", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The transaction ID to return." + }, + { + "description": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data.", + "name": "verbose", + "schema": { + "format": "uint8", + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "summary": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data." + }, + { + "description": "The hash of the block to return.", + "name": "block_hash", + "schema": { + "type": "string" + }, + "summary": "The hash of the block to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getrawtransaction_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the raw transaction data, as a [`GetRawTransaction`] JSON string or structure.", + "x-server": "zebra" + }, + { + "description": "Checks if a zcash address of type P2PKH, P2SH, TEX, SAPLING or UNIFIED is valid.\nReturns information about the given address if valid.\n\nzcashd reference: [`z_validateaddress`](https://zcash.github.io/rpc/z_validateaddress.html)\nmethod: post\ntags: util\n\n# Parameters\n\n- `address`: (string, required) The zcash address to validate.\n\n# Notes\n\n- No notes", + "name": "z_validateaddress", + "params": [ + { + "description": "The address to return.", + "name": "address", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The address to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "z_validateaddress_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Checks if a zcash address of type P2PKH, P2SH, TEX, SAPLING or UNIFIED is valid.", + "x-server": "zebra" + }, + { + "description": "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.\n\nzcashd reference: [`getdifficulty`](https://zcash.github.io/rpc/getdifficulty.html)\nmethod: post\ntags: blockchain", + "name": "getdifficulty", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getdifficulty_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.", + "x-server": "zebra" + }, + { + "description": "Returns data about each connected network node.\n\nzcashd reference: [`getpeerinfo`](https://zcash.github.io/rpc/getpeerinfo.html)\nmethod: post\ntags: network", + "name": "getpeerinfo", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getpeerinfo_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns data about each connected network node.", + "x-server": "zebra" + }, + { + "description": "Returns an object containing various state info regarding P2P networking.\n\nzcashd reference: [`getnetworkinfo`](https://zcash.github.io/rpc/getnetworkinfo.html)\nmethod: post\ntags: network", + "name": "getnetworkinfo", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getnetworkinfo_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns an object containing various state info regarding P2P networking.", + "x-server": "zebra" + }, + { + "description": "Returns the list of individual payment addresses given a unified address.\n\nzcashd reference: [`z_listunifiedreceivers`](https://zcash.github.io/rpc/z_listunifiedreceivers.html)\nmethod: post\ntags: wallet\n\n# Parameters\n\n- `address`: (string, required) The zcash unified address to get the list from.\n\n# Notes\n\n- No notes", + "name": "z_listunifiedreceivers", + "params": [ + { + "description": "The address to return.", + "name": "address", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The address to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "z_listunifiedreceivers_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the list of individual payment addresses given a unified address.", + "x-server": "zebra" + }, + { + "description": "Returns information about the given block's Sapling & Orchard tree state.\n\nzcashd reference: [`z_gettreestate`](https://zcash.github.io/rpc/z_gettreestate.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `hash | height`: (string, required, example=\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\") The block hash or height.\n\n# Notes\n\nThe zcashd doc reference above says that the parameter \"`height` can be\nnegative where -1 is the last known valid block\". On the other hand,\n`lightwalletd` only uses positive heights, so Zebra does not support\nnegative heights.", + "name": "z_gettreestate", + "params": [ + { + "description": "The block hash or height to return.", + "name": "hash_or_height", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The block hash or height to return." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "z_gettreestate_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns information about the given block's Sapling & Orchard tree state.", + "x-server": "zebra" + }, + { + "description": "Returns a block template for mining new Zcash blocks.\n\n# Parameters\n\n- `jsonrequestobject`: (string, optional) A JSON object containing arguments.\n\nzcashd reference: [`getblocktemplate`](https://zcash-rpc.github.io/getblocktemplate.html)\nmethod: post\ntags: mining\n\n# Notes\n\nArguments to this RPC are currently ignored.\nLong polling, block proposals, server lists, and work IDs are not supported.\n\nMiners can make arbitrary changes to blocks, as long as:\n- the data sent to `submitblock` is a valid Zcash block, and\n- the parent block is a valid block that Zebra already has, or will receive soon.\n\nZebra verifies blocks in parallel, and keeps recent chains in parallel,\nso moving between chains and forking chains is very cheap.", + "name": "getblocktemplate", + "params": [ + { + "description": "The parameters for the command.", + "name": "parameters", + "schema": { + "$ref": "#/components/schemas/GetBlockTemplateParameters" + }, + "summary": "The parameters for the command." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getblocktemplate_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns a block template for mining new Zcash blocks.", + "x-server": "zebra" + }, + { + "description": "Returns the requested block by hash or height, as a [`GetBlock`] JSON string.\nIf the block is not in Zebra's state, returns\n[error code `-8`.](https://github.com/zcash/zcash/issues/5758) if a height was\npassed or -5 if a hash was passed.\n\nzcashd reference: [`getblock`](https://zcash.github.io/rpc/getblock.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `hash_or_height`: (string, required, example=\"1\") The hash or height for the block to be returned.\n- `verbosity`: (number, optional, default=1, example=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data.\n\n# Notes\n\nThe `size` field is only returned with verbosity=2.\n\nThe undocumented `chainwork` field is not returned.", + "name": "getblock", + "params": [ + { + "description": "The block hash or height to return.", + "name": "hash_or_height", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The block hash or height to return." + }, + { + "description": "Whether to include verbose output.", + "name": "verbosity", + "schema": { + "format": "uint8", + "maximum": 255, + "minimum": 0, + "type": "integer" + }, + "summary": "Whether to include verbose output." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getblock_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the requested block by hash or height, as a [`GetBlock`] JSON string.", + "x-server": "zebra" + }, + { + "description": "Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string.\nIf the block is not in Zebra's state,\nreturns [error code `-8`.](https://github.com/zcash/zcash/issues/5758)\nif a height was passed or -5 if a hash was passed.\n\nzcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `hash_or_height`: (string, required, example=\"1\") The hash or height for the block to be returned.\n- `verbose`: (bool, optional, default=false, example=true) false for hex encoded data, true for a json object\n\n# Notes\n\nThe undocumented `chainwork` field is not returned.", + "name": "getblockheader", + "params": [ + { + "description": "The block hash or height to return.", + "name": "hash_or_height", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The block hash or height to return." + }, + { + "description": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data.", + "name": "verbose", + "schema": { + "type": "boolean" + }, + "summary": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data." + } + ], + "result": { + "description": "An OpenRPC document.", + "name": "getblockheader_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string.", + "x-server": "zebra" + }, + { + "description": "Returns details on the active state of the TX memory pool.\n\nzcash reference: [`getmempoolinfo`](https://zcash.github.io/rpc/getmempoolinfo.html)", + "name": "getmempoolinfo", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "getmempoolinfo_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns details on the active state of the TX memory pool.", + "x-server": "zebra" + }, + { + "description": "Send a transaction with multiple recipients.\n\nThis is an async operation; it returns an operation ID string that you can pass to\n`z_getoperationstatus` or `z_getoperationresult`.\n\nAmounts are decimal numbers with at most 8 digits of precision.\n\nChange generated from one or more transparent addresses flows to a new transparent\naddress, while change generated from a legacy Sapling address returns to itself.\nTODO: https://github.com/zcash/wallet/issues/138\n\nWhen sending from a unified address, change is returned to the internal-only\naddress for the associated unified account.\n\nWhen spending coinbase UTXOs, only shielded recipients are permitted and change is\nnot allowed; the entire value of the coinbase UTXO(s) must be consumed.\nTODO: https://github.com/zcash/wallet/issues/137\n\n# Arguments\n\n- `fromaddress` (string, required) The transparent or shielded address to send the\n funds from. The following special strings are also accepted:\n - `\"ANY_TADDR\"`: Select non-coinbase UTXOs from any transparent addresses\n belonging to the wallet. Use `z_shieldcoinbase` to shield coinbase UTXOs from\n multiple transparent addresses.\n If a unified address is provided for this argument, the TXOs to be spent will be\n selected from those associated with the account corresponding to that unified\n address, from value pools corresponding to the receivers included in the UA.\n- `amounts` (array, required) An array of JSON objects representing the amounts to\n send, with the following fields:\n - `address` (string, required) A taddr, zaddr, or Unified Address.\n - `amount` (numeric, required) The numeric amount in ZEC.\n - `memo` (string, optional) If the address is a zaddr, raw data represented in\n hexadecimal string format. If the output is being sent to a transparent\n address, it’s an error to include this field.\n- `minconf` (numeric, optional) Only use funds confirmed at least this many times.\n- `fee` (numeric, optional) If set, it must be null. Zallet always uses a fee\n calculated according to ZIP 317.\n- `privacy_policy` (string, optional, default=`\"FullPrivacy\"`) Policy for what\n information leakage is acceptable. One of the following strings:\n - `\"FullPrivacy\"`: Only allow fully-shielded transactions (involving a single\n shielded value pool).\n - `\"AllowRevealedAmounts\"`: Allow funds to cross between shielded value pools,\n revealing the amount that crosses pools.\n - `\"AllowRevealedRecipients\"`: Allow transparent recipients. This also implies\n revealing information described under `\"AllowRevealedAmounts\"`.\n - `\"AllowRevealedSenders\"`: Allow transparent funds to be spent, revealing the\n sending addresses and amounts. This implies revealing information described\n under `\"AllowRevealedAmounts\"`.\n - `\"AllowFullyTransparent\"`: Allow transaction to both spend transparent funds\n and have transparent recipients. This implies revealing information described\n under `\"AllowRevealedSenders\"` and `\"AllowRevealedRecipients\"`.\n - `\"AllowLinkingAccountAddresses\"`: Allow selecting transparent coins from the\n full account, rather than just the funds sent to the transparent receiver in\n the provided Unified Address. This implies revealing information described\n under `\"AllowRevealedSenders\"`.\n - `\"NoPrivacy\"`: Allow the transaction to reveal any information necessary to\n create it. This implies revealing information described under\n `\"AllowFullyTransparent\"` and `\"AllowLinkingAccountAddresses\"`.", + "name": "z_sendmany", + "params": [ + { + "description": "The transparent or shielded address to send the funds from.", + "name": "fromaddress", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The transparent or shielded address to send the funds from." + }, + { + "description": "An array of JSON objects representing the amounts to send.", + "name": "amounts", + "required": true, + "schema": { + "items": { + "$ref": "#/components/schemas/AmountParameter" + }, + "type": "array" + }, + "summary": "An array of JSON objects representing the amounts to send." + }, + { + "description": "Only use funds confirmed at least this many times.", + "name": "minconf", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "Only use funds confirmed at least this many times." + }, + { + "description": "If set, it must be null.", + "name": "fee", + "schema": true, + "summary": "If set, it must be null." + }, + { + "description": "Policy for what information leakage is acceptable.", + "name": "privacy_policy", + "schema": { + "type": "string" + }, + "summary": "Policy for what information leakage is acceptable." + } + ], + "result": { + "description": "An async operation ID.", + "name": "z_sendmany_result", + "schema": { + "$ref": "#/components/schemas/OperationId" + }, + "summary": "An async operation ID." + }, + "summary": "Send a transaction with multiple recipients.", + "x-server": "zallet" + }, + { + "description": "For the given account, derives a Unified Address in accordance with the remaining\narguments:\n\n- If no list of receiver types is given (or the empty list `[]`), the best and\n second-best shielded receiver types, along with the \"p2pkh\" (i.e. transparent)\n receiver type, will be used.\n- If no diversifier index is given, then:\n - If a transparent receiver would be included (either because no list of\n receiver types is given, or the provided list includes \"p2pkh\"), the next\n unused index (that is valid for the list of receiver types) will be selected.\n - If only shielded receivers would be included (because a list of receiver types\n is given that does not include \"p2pkh\"), a time-based index will be selected.\n\nThe account parameter must be a UUID or account number that was previously\ngenerated by a call to the `z_getnewaccount` RPC method. The legacy account number\nis only supported for wallets containing a single seed phrase.\n\nOnce a Unified Address has been derived at a specific diversifier index,\nre-deriving it (via a subsequent call to `z_getaddressforaccount` with the same\naccount and index) will produce the same address with the same list of receiver\ntypes. An error will be returned if a different list of receiver types is\nrequested, including when the empty list `[]` is provided (if the default receiver\ntypes don't match).", + "name": "z_getaddressforaccount", + "params": [ + { + "description": "Either the UUID or ZIP 32 account index of the account to derive from.", + "name": "account", + "required": true, + "schema": true, + "summary": "Either the UUID or ZIP 32 account index of the account to derive from." + }, + { + "description": "Receiver types to include in the derived address.", + "name": "receiver_types", + "schema": { + "items": { + "type": "string" + }, + "type": "array" + }, + "summary": "Receiver types to include in the derived address." + }, + { + "description": "A specific diversifier index to derive at.", + "name": "diversifier_index", + "schema": { + "format": "uint128", + "minimum": 0, + "type": "integer" + }, + "summary": "A specific diversifier index to derive at." + } + ], + "result": { + "description": "Information about a derived Unified Address.", + "name": "z_getaddressforaccount_result", + "schema": { + "$ref": "#/components/schemas/Address" + }, + "summary": "Information about a derived Unified Address." + }, + "summary": "For the given account, derives a Unified Address in accordance with the remaining", + "x-server": "zallet" + }, + { + "description": "Returns the total value of funds stored in the node's wallet.\n\nTODO: Currently watchonly addresses cannot be omitted; `include_watchonly` must be\nset to true.\n\n# Arguments\n\n- `minconf` (numeric, optional, default=1) Only include private and transparent\n transactions confirmed at least this many times.\n- `include_watchonly` (bool, optional, default=false) Also include balance in\n watchonly addresses (see 'importaddress' and 'z_importviewingkey').", + "name": "z_gettotalbalance", + "params": [ + { + "description": "Only include notes in transactions confirmed at least this many times.", + "name": "minconf", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "Only include notes in transactions confirmed at least this many times." + }, + { + "description": "Also include balance in watchonly addresses.", + "name": "include_watchonly", + "schema": { + "type": "boolean" + }, + "summary": "Also include balance in watchonly addresses." + } + ], + "result": { + "description": "The total value of funds stored in the wallet.", + "name": "z_gettotalbalance_result", + "schema": { + "$ref": "#/components/schemas/TotalBalance" + }, + "summary": "The total value of funds stored in the wallet." + }, + "summary": "Returns the total value of funds stored in the node's wallet.", + "x-server": "zallet" + }, + { + "description": "Removes the wallet encryption key from memory, locking the wallet.\n\nAfter calling this method, you will need to call `walletpassphrase` again before\nbeing able to call any methods which require the wallet to be unlocked.", + "name": "walletlock", + "params": [], + "result": { + "description": "Empty result indicating success.", + "name": "walletlock_result", + "schema": { + "$ref": "#/components/schemas/ResultType" + }, + "summary": "Empty result indicating success." + }, + "summary": "Removes the wallet encryption key from memory, locking the wallet.", + "x-server": "zallet" + }, + { + "description": "Prepares and returns a new account.\n\nIf the wallet contains more than one UA-compatible HD seed phrase, the `seedfp`\nargument must be provided. Available seed fingerprints can be found in the output\nof the `listaddresses` RPC method.\n\nWithin a UA-compatible HD seed phrase, accounts are numbered starting from zero;\nthis RPC method selects the next available sequential account number.\n\nEach new account is a separate group of funds within the wallet, and adds an\nadditional performance cost to wallet scanning.\n\nUse the `z_getaddressforaccount` RPC method to obtain addresses for an account.", + "name": "z_getnewaccount", + "params": [ + { + "description": "A human-readable name for the account.", + "name": "account_name", + "required": true, + "schema": { + "type": "string" + }, + "summary": "A human-readable name for the account." + }, + { + "description": "ZIP 32 seed fingerprint for the BIP 39 mnemonic phrase from which to derive the account.", + "name": "seedfp", + "schema": { + "type": "string" + }, + "summary": "ZIP 32 seed fingerprint for the BIP 39 mnemonic phrase from which to derive the account." + } + ], + "result": { + "description": "Information about the new account.", + "name": "z_getnewaccount_result", + "schema": { + "$ref": "#/components/schemas/Account" + }, + "summary": "Information about the new account." + }, + "summary": "Prepares and returns a new account.", + "x-server": "zallet" + }, + { + "description": "List all commands, or get help for a specified command.\n\n# Arguments\n- `command` (string, optional) The command to get help on.", + "name": "help", + "params": [ + { + "description": "The command to get help on.", + "name": "command", + "schema": { + "type": "string" + }, + "summary": "The command to get help on." + } + ], + "result": { + "description": "The help response.", + "name": "help_result", + "schema": { + "$ref": "#/components/schemas/ResultType2" + }, + "summary": "The help response." + }, + "summary": "List all commands, or get help for a specified command.", + "x-server": "zallet" + }, + { + "description": "Stop the running zallet process.\n\n# Notes\n\n- Works for non windows targets only.\n- Works only if the network of the running zallet process is `Regtest`.", + "name": "stop", + "params": [], + "result": { + "description": "The stop response.", + "name": "stop_result", + "schema": { + "$ref": "#/components/schemas/ResultType3" + }, + "summary": "The stop response." + }, + "summary": "Stop the running zallet process.", + "x-server": "zallet" + }, + { + "description": "Retrieve the result and status of an operation which has finished, and then remove\nthe operation from memory.\n\n- If the operation has failed, it will include an error object.\n- If the operation has succeeded, it will include the result value.\n- If the operation was cancelled, there will be no error object or result value.\n\n# Arguments\n- `operationid` (array, optional) A list of operation ids we are interested in.\n If not provided, retrieve all finished operations known to the node.", + "name": "z_getoperationresult", + "params": [ + { + "description": "A list of operation ids we are interested in.", + "name": "operationid", + "schema": { + "items": { + "$ref": "#/components/schemas/OperationId" + }, + "type": "array" + }, + "summary": "A list of operation ids we are interested in." + } + ], + "result": { + "description": "The relevant operations.", + "name": "z_getoperationresult_result", + "schema": { + "$ref": "#/components/schemas/ResultType4" + }, + "summary": "The relevant operations." + }, + "summary": "Retrieve the result and status of an operation which has finished, and then remove", + "x-server": "zallet" + }, + { + "description": "Get operation status and any associated result or error data.\n\nThe operation will remain in memory.\n\n- If the operation has failed, it will include an error object.\n- If the operation has succeeded, it will include the result value.\n- If the operation was cancelled, there will be no error object or result value.\n\n# Arguments\n- `operationid` (array, optional) A list of operation ids we are interested in.\n If not provided, examine all operations known to the node.", + "name": "z_getoperationstatus", + "params": [ + { + "description": "A list of operation ids we are interested in.", + "name": "operationid", + "schema": { + "items": { + "$ref": "#/components/schemas/OperationId" + }, + "type": "array" + }, + "summary": "A list of operation ids we are interested in." + } + ], + "result": { + "description": "The relevant operations.", + "name": "z_getoperationstatus_result", + "schema": { + "$ref": "#/components/schemas/ResultType4" + }, + "summary": "The relevant operations." + }, + "summary": "Get operation status and any associated result or error data.", + "x-server": "zallet" + }, + { + "description": "Returns detailed information about in-wallet transaction `txid`.\n\nThis method returns information about spends and outputs within the transaction\nthat are visible to the wallet. Importantly, this does not include information\nabout spent notes that are not controlled by spending or viewing keys in the\nwallet, and so callers MUST NOT use the `spends` or `outputs` fields to compute\nbalances or fees themselves. Use the provided `accounts` and `fee` fields instead.", + "name": "z_viewtransaction", + "params": [ + { + "description": "The ID of the transaction to view.", + "name": "txid", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The ID of the transaction to view." + } + ], + "result": { + "description": "Detailed information about an in-wallet transaction.", + "name": "z_viewtransaction_result", + "schema": { + "$ref": "#/components/schemas/Transaction" + }, + "summary": "Detailed information about an in-wallet transaction." + }, + "summary": "Returns detailed information about in-wallet transaction `txid`.", + "x-server": "zallet" + }, + { + "description": "Stores the wallet decryption key in memory for `timeout` seconds.\n\nIf the wallet is locked, this API must be invoked prior to performing operations\nthat require the availability of private keys, such as sending funds.\n\nIssuing the `walletpassphrase` command while the wallet is already unlocked will\nset a new unlock time that overrides the old one.", + "name": "walletpassphrase", + "params": [ + { + "description": "The passphrase for decrypting the wallet's age identity.", + "name": "passphrase", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The passphrase for decrypting the wallet's age identity." + }, + { + "description": "Time in seconds after which the wallet will relock.", + "name": "timeout", + "required": true, + "schema": { + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "summary": "Time in seconds after which the wallet will relock." + } + ], + "result": { + "description": "Empty result indicating success.", + "name": "walletpassphrase_result", + "schema": { + "$ref": "#/components/schemas/ResultType5" + }, + "summary": "Empty result indicating success." + }, + "summary": "Stores the wallet decryption key in memory for `timeout` seconds.", + "x-server": "zallet" + }, + { + "description": "Returns a list of the wallet's transactions, optionally filtered by account and block\nrange.\n\n# Arguments\n- `account_uuid`: The UUID of the wallet account. If omitted, return transactions for all\n accounts in the wallet.\n- `start_height`: The inclusive lower bound of block heights for which transactions mined\n in those blocks should be returned. If omitted, the start height will default to the\n account birthday height if an account UUID is specified, or the minimum birthday\n height among accounts in the wallet if no account is specified.\n- `end_height`: The exclusive upper bound of block heights for which transactions mined\n in those blocks should be returned. If omitted, return all transactions mined or created\n above the start height.\n- `offset`: An optional number of transactions to skip over before a page of results is\n returned. Defaults to zero.\n- `limit`: An optional upper bound on the number of results that should be returned in a\n page. \n\nWARNING: This is currently an experimental feature; arguments and result data may change at\nany time.", + "name": "z_listtransactions", + "params": [ + { + "description": "The UUID of the account to list transactions for.", + "name": "account_uuid", + "schema": { + "type": "string" + }, + "summary": "The UUID of the account to list transactions for." + }, + { + "description": "The (inclusive) lower bound on block heights for which transactions should be retrieved", + "name": "start_height", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "The (inclusive) lower bound on block heights for which transactions should be retrieved" + }, + { + "description": "The (exclusive) upper bound on block heights for which transactions should be retrieved", + "name": "end_height", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "The (exclusive) upper bound on block heights for which transactions should be retrieved" + }, + { + "description": "The number of results to skip before returning a page of results.", + "name": "offset", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "The number of results to skip before returning a page of results." + }, + { + "description": "The maximum number of results to return from a single call.", + "name": "limit", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "The maximum number of results to return from a single call." + } + ], + "result": { + "description": "A list of transactions involving the wallet.", + "name": "z_listtransactions_result", + "schema": { + "$ref": "#/components/schemas/ResultType6" + }, + "summary": "A list of transactions involving the wallet." + }, + "summary": "Returns a list of the wallet's transactions, optionally filtered by account and block", + "x-server": "zallet" + }, + { + "description": "", + "name": "z_listaccounts", + "params": [], + "result": { + "description": "A list of accounts.", + "name": "z_listaccounts_result", + "schema": { + "$ref": "#/components/schemas/ResultType7" + }, + "summary": "A list of accounts." + }, + "summary": "", + "x-server": "zallet" + }, + { + "description": "Returns wallet state information.", + "name": "getwalletinfo", + "params": [], + "result": { + "description": "The wallet state information.", + "name": "getwalletinfo_result", + "schema": { + "$ref": "#/components/schemas/GetWalletInfo" + }, + "summary": "The wallet state information." + }, + "summary": "Returns wallet state information.", + "x-server": "zallet" + }, + { + "description": "Returns the number of notes available in the wallet for each shielded value pool.\n\n# Arguments\n- `minconf`: Only include notes in transactions confirmed at least this many times\n (default = 1). Must be at least 1 when `as_of_height` is provided.\n- `as_of_height`: Execute the query as if it were run when the blockchain was at the height\n specified by this argument. The default is to use the entire blockchain that the node is\n aware of. -1 can be used as in other RPC calls to indicate the current height (including\n the mempool), but this does not support negative values in general. A “future” height will\n fall back to the current height.", + "name": "z_getnotescount", + "params": [ + { + "description": "Only include notes in transactions confirmed at least this many times.", + "name": "minconf", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "Only include notes in transactions confirmed at least this many times." + }, + { + "description": "Execute the query as if it were run when the blockchain was at the height specified by this argument.", + "name": "as_of_height", + "schema": { + "format": "int64", + "type": "integer" + }, + "summary": "Execute the query as if it were run when the blockchain was at the height specified by this argument." + } + ], + "result": { + "description": "The number of notes in the wallet.", + "name": "z_getnotescount_result", + "schema": { + "$ref": "#/components/schemas/GetNotesCount" + }, + "summary": "The number of notes in the wallet." + }, + "summary": "Returns the number of notes available in the wallet for each shielded value pool.", + "x-server": "zallet" + }, + { + "description": "Returns a record of the individual receivers contained within the provided UA,\nkeyed by receiver type. The UA may not have receivers for some receiver types,\nin which case those keys will be absent.\n\nTransactions that send funds to any of the receivers returned by this RPC\nmethod will be detected by the wallet as having been sent to the unified\naddress.\n\n# Arguments\n- `unified_address` (string, required) The unified address to inspect.", + "name": "z_listunifiedreceivers", + "params": [ + { + "description": "The unified address to inspect.", + "name": "unified_address", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The unified address to inspect." + } + ], + "result": { + "description": "The receivers within a unified address.", + "name": "z_listunifiedreceivers_result", + "schema": { + "$ref": "#/components/schemas/ListUnifiedReceivers" + }, + "summary": "The receivers within a unified address." + }, + "summary": "Returns a record of the individual receivers contained within the provided UA,", + "x-server": "zallet" + }, + { + "description": "Returns the list of operation ids currently known to the wallet.\n\n# Arguments\n- `status` (string, optional) Filter result by the operation's state e.g. \"success\".", + "name": "z_listoperationids", + "params": [ + { + "description": "Filter result by the operation's state e.g. \"success\".", + "name": "status", + "schema": { + "type": "string" + }, + "summary": "Filter result by the operation's state e.g. \"success\"." + } + ], + "result": { + "description": "A list of operation IDs.", + "name": "z_listoperationids_result", + "schema": { + "$ref": "#/components/schemas/ResultType8" + }, + "summary": "A list of operation IDs." + }, + "summary": "Returns the list of operation ids currently known to the wallet.", + "x-server": "zallet" + }, + { + "description": "Returns an array of unspent shielded notes with between minconf and maxconf\n(inclusive) confirmations.\n\nResults may be optionally filtered to only include notes sent to specified\naddresses. When `minconf` is 0, unspent notes with zero confirmations are\nreturned, even though they are not immediately spendable.\n\n# Arguments\n- `minconf`: Select outputs with at least this many confirmations (default = 1). Must be at\n least 1 when `as_of_height` is provided.\n- `maxconf`: Select outputs with at most this many confirmations (default = unlimited).\n- `include_watchonly`: Include notes/utxos for which the wallet does not provide spending\n capability (default = false).\n- `addresses`: A list of addresses for which to retrieve UTXOs. For shielded addresses that\n correspond to a unified account, unspent notes belonging to that account are returned\n irrespective of whether the provided address's diversifier corresponds to the diversifier\n of the address that received the funds. If this parameter is omitted or empty, all notes\n are returned, irrespective of account. (default = None)\n- `as_of_height`: Execute the query as if it were run when the blockchain was at the height\n specified by this argument. The default is to use the entire blockchain that the node is\n aware of. -1 can be used as in other RPC calls to indicate the current height (including\n the mempool), but this does not support negative values in general. A “future” height will\n fall back to the current height.", + "name": "z_listunspent", + "params": [ + { + "description": "Only include outputs of transactions confirmed at least this many times.", + "name": "minconf", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "Only include outputs of transactions confirmed at least this many times." + }, + { + "description": "Only include outputs of transactions confirmed at most this many times.", + "name": "maxconf", + "schema": { + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "summary": "Only include outputs of transactions confirmed at most this many times." + }, + { + "description": "Also include outputs received at watch-only addresses.", + "name": "include_watchonly", + "schema": { + "type": "boolean" + }, + "summary": "Also include outputs received at watch-only addresses." + }, + { + "description": "If non-empty, only outputs received by the provided addresses will be returned.", + "name": "addresses", + "schema": { + "items": { + "type": "string" + }, + "type": "array" + }, + "summary": "If non-empty, only outputs received by the provided addresses will be returned." + }, + { + "description": "Execute the query as if it were run when the blockchain was at the height specified by this argument.", + "name": "as_of_height", + "schema": { + "format": "int64", + "type": "integer" + }, + "summary": "Execute the query as if it were run when the blockchain was at the height specified by this argument." + } + ], + "result": { + "description": "A list of unspent notes.", + "name": "z_listunspent_result", + "schema": { + "$ref": "#/components/schemas/ResultType9" + }, + "summary": "A list of unspent notes." + }, + "summary": "Returns an array of unspent shielded notes with between minconf and maxconf", + "x-server": "zallet" + }, + { + "description": "Tells the wallet to track specific accounts.\n\nReturns the UUIDs within this Zallet instance of the newly-tracked accounts.\nAccounts that are already tracked by the wallet are ignored.\n\nAfter calling this method, a subsequent call to `z_getnewaccount` will add the\nfirst account with index greater than all indices provided here for the\ncorresponding `seedfp` (as well as any already tracked by the wallet).\n\nEach tracked account is a separate group of funds within the wallet, and adds an\nadditional performance cost to wallet scanning.\n\nUse the `z_getaddressforaccount` RPC method to obtain addresses for an account.\n\n# Arguments\n\n- `accounts` (array, required) An array of JSON objects representing the accounts\n to recover, with the following fields:\n - `name` (string, required)\n - `seedfp` (string, required) The seed fingerprint for the mnemonic phrase from\n which the account is derived. Available seed fingerprints can be found in the\n output of the `listaddresses` RPC method.\n - `zip32_account_index` (numeric, required)\n - `birthday_height` (numeric, required)", + "name": "z_recoveraccounts", + "params": [ + { + "description": "An array of JSON objects representing the accounts to recover.", + "name": "accounts", + "required": true, + "schema": { + "items": { + "$ref": "#/components/schemas/AccountParameter" + }, + "type": "array" + }, + "summary": "An array of JSON objects representing the accounts to recover." + } + ], + "result": { + "description": "The list of recovered accounts.", + "name": "z_recoveraccounts_result", + "schema": { + "$ref": "#/components/schemas/Accounts" + }, + "summary": "The list of recovered accounts." + }, + "summary": "Tells the wallet to track specific accounts.", + "x-server": "zallet" + }, + { + "description": "Returns the raw transaction data for the given transaction ID.\n\nNOTE: If `blockhash` is provided, only that block will be searched, and if the\ntransaction is in the mempool or other blocks, or if the node backing this wallet\ndoes not have the given block available, the transaction will not be found.\n\n# Arguments\n- `txid` (string, required) The transaction ID.\n- `verbose` (numeric, optional, default=0) If 0, return a string of hex-encoded\n data. If non-zero, return a JSON object with information about `txid`.\n- `blockhash` (string, optional) The block in which to look for the transaction.", + "name": "getrawtransaction", + "params": [ + { + "description": "The ID of the transaction to fetch.", + "name": "txid", + "required": true, + "schema": { + "type": "string" + }, + "summary": "The ID of the transaction to fetch." + }, + { + "description": "If 0, return a string of hex-encoded data. If non-zero, return a JSON object with information about `txid`", + "name": "verbose", + "schema": { + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "summary": "If 0, return a string of hex-encoded data. If non-zero, return a JSON object with information about `txid`" + }, + { + "description": "The block in which to look for the transaction.", + "name": "blockhash", + "schema": { + "type": "string" + }, + "summary": "The block in which to look for the transaction." + } + ], + "result": { + "description": "The `getrawtransaction` response.", + "name": "getrawtransaction_result", + "schema": { + "$ref": "#/components/schemas/ResultType10" + }, + "summary": "The `getrawtransaction` response." + }, + "summary": "Returns the raw transaction data for the given transaction ID.", + "x-server": "zallet" + }, + { + "description": "Returns an OpenRPC schema as a description of this service.", + "name": "rpc.discover", + "params": [], + "result": { + "description": "An OpenRPC document.", + "name": "rpc.discover_result", + "schema": { + "$ref": "#/components/schemas/OpenRPC%20Schema" + }, + "summary": "An OpenRPC document." + }, + "summary": "Returns an OpenRPC schema as a description of this service.", + "x-server": "zallet" + }, + { + "description": "Lists the addresses managed by this wallet by source.\n\nSources include:\n- Addresses generated from randomness by a legacy `zcashd` wallet.\n- Sapling addresses generated from the legacy `zcashd` HD seed.\n- Imported watchonly transparent addresses.\n- Shielded addresses tracked using imported viewing keys.\n- Addresses derived from mnemonic seed phrases.\n\nIn the case that a source does not have addresses for a value pool, the key\nassociated with that pool will be absent.\n\nREMINDER: It is recommended that you back up your wallet files regularly. If you\nhave not imported externally-produced keys, it only necessary to have backed up\nthe wallet's key storage file.", + "name": "listaddresses", + "params": [], + "result": { + "description": "A list of address sources.", + "name": "listaddresses_result", + "schema": { + "$ref": "#/components/schemas/ResultType11" + }, + "summary": "A list of address sources." + }, + "summary": "Lists the addresses managed by this wallet by source.", + "x-server": "zallet" + } + ], + "openrpc": "1.3.2", + "servers": [ + { + "name": "router", + "url": "http://localhost:8080/" + } + ] +} \ No newline at end of file From 5b4379e8bdb1dc6f084a93c3f8f1b18ddb2a356d Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 17 Dec 2025 19:02:25 -0300 Subject: [PATCH 04/27] add schema url --- rpc-router/src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 80f7ee1..88b7731 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -333,6 +333,9 @@ async fn main() -> Result<()> { let listener = TcpListener::bind(addr).await?; info!("RPC Router listening on {}", addr); + info!("You can use the following playground URL:"); + info!("https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false&uiSchema[appBar]"); + loop { let (stream, _) = listener.accept().await?; let io = TokioIo::new(stream); From adba5b6dd946692a81a0b2bc93011e90c544aa89 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 18 Dec 2025 15:58:43 -0300 Subject: [PATCH 05/27] add a README --- rpc-router/src/README.md | 111 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 rpc-router/src/README.md diff --git a/rpc-router/src/README.md b/rpc-router/src/README.md new file mode 100644 index 0000000..80f140b --- /dev/null +++ b/rpc-router/src/README.md @@ -0,0 +1,111 @@ +# Z3 RPC Router + +The **Z3 RPC Router** (`rpc-router` crate) provides a single JSON-RPC endpoint on top of the Zebra and Zallet RPC servers. + +It exposes a new port where incoming RPC requests are transparently routed to the appropriate backend: + +- RPC methods belonging to Zebra are forwarded to the Zebra RPC endpoint. +- RPC methods belonging to Zallet are forwarded to the Zallet RPC endpoint. + +From the point of view of a dApp built on top of the Zcash Z3 stack, this means there is a single RPC endpoint to interact with, while all routing happens in the background. + +In addition to request routing, the router also: + +- Calls `rpc.discover` on both Zebra and Zallet at startup +- Builds a merged OpenRPC schema for the Z3 stack +- Exposes the merged schema via its own `rpc.discover` method +- Saves the merged schema to a local `z3_merged.json` file on startup + +## Developer Usage + +To run the router, Zebra and Zallet must already be running and listening on known ports. + +The router accepts this configuration via environment variables, or alternatively you can modify the values directly in main.rs. + +### Running Zebra and Zallet for Development + +For development and testing purposes, a helper utility was added to Zebra as part of the QA testing framework. This utility spawns both Zebra and Zallet in regtest mode. + +You can start both servers by running: + +```bash +python3 qa/rpc-tests/openrpc.py +``` + +Example output: + +```bash +Keeping the test alive for 7200 seconds... +Zebra running at http://localhost:18666/ +Zallet running at http://localhost:23666/ +``` + +These two endpoints are then used by the RPC router. + +### Running the RPC Router + +```bash +RUST_LOG=info \ +ZEBRA_URL=http://localhost:18666/ \ +ZALLET_URL=http://localhost:23666/ \ +cargo run +``` + +Example output: + +```bash +INFO rpc_router: Saved merged schema to z3_merged.json +INFO rpc_router: RPC Router listening on 0.0.0.0:8080 +INFO rpc_router: You can use the following playground URL: +INFO rpc_router: https://playground.open-rpc.org/?... +``` + +At this point, the router is listening on `http://localhost:8080`. + +### Querying the Router + +You can use standard JSON-RPC clients (such as `curl`) to call methods exposed by either Zebra or Zallet through the router. + +#### Example: Zebra RPC Call + +```bash +curl --silent -X POST \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"getinfo","params":[],"id":123}' \ + http://127.0.0.1:8080 | jq +``` + +On the router side, you should see: + +```bash +INFO rpc_router: Routing getinfo to Zebra +``` + +#### Example: Zallet RPC Call + +```bash +curl --silent -X POST \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"getwalletinfo","params":[],"id":123}' \ + http://127.0.0.1:8080 | jq +``` + +And on the router logs: + +```bash +INFO rpc_router: Routing getwalletinfo to Zallet +``` + +### OpenRPC Playground + +You can also interact with the merged OpenRPC schema using the OpenRPC Playground. The playground is configured to use the merged schema generated by the router. + +[Playground](https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false&uiSchema[appBar]) + +When using the inspector, make sure the target server URL is set to: + +``` +http://localhost:8080/ +``` + +The RPC router automatically sets the required CORS headers, allowing the playground (or other browser-based tools) to call the local endpoint directly. From 27632a0cba08d7f60cbe247622ccf70661e2d44b Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 18 Dec 2025 17:36:24 -0300 Subject: [PATCH 06/27] fix playground url --- rpc-router/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 88b7731..2c06e1d 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -334,7 +334,7 @@ async fn main() -> Result<()> { info!("RPC Router listening on {}", addr); info!("You can use the following playground URL:"); - info!("https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false&uiSchema[appBar]"); + info!("https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"); loop { let (stream, _) = listener.accept().await?; From 675b8e17e55acfa634074100438602b8550d8eb9 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 19 Dec 2025 09:55:44 -0300 Subject: [PATCH 07/27] move readme --- rpc-router/{src => }/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rpc-router/{src => }/README.md (100%) diff --git a/rpc-router/src/README.md b/rpc-router/README.md similarity index 100% rename from rpc-router/src/README.md rename to rpc-router/README.md From 2e074953226ad51af8d2c7101611a79f5dab24cd Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:18:03 -0300 Subject: [PATCH 08/27] fix panic --- rpc-router/src/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 2c06e1d..93c2523 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -249,9 +249,11 @@ fn extract_methods_array(schema: &Value) -> Vec { /// Annotates each method with its origin server. fn annotate_methods_with_server(methods: &mut Vec, server_name: &str) { for m in methods { - m.as_object_mut() - .unwrap() - .insert("x-server".to_string(), json!(server_name)); + if let Some(obj) = m.as_object_mut() { + obj.insert("x-server".to_string(), json!(server_name)); + } else { + warn!("Skipping non-object method entry while annotating for {}", server_name); + } } } From 7efb9b39b2e495995bc89cb064ce1f4445fc9dcd Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:22:56 -0300 Subject: [PATCH 09/27] rpc-router: add unit tests for schema merging and routing logic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rpc-router/src/main.rs | 3 + rpc-router/src/tests.rs | 135 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 rpc-router/src/tests.rs diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 93c2523..e8c1023 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -357,3 +357,6 @@ async fn main() -> Result<()> { }); } } + +#[cfg(test)] +mod tests; diff --git a/rpc-router/src/tests.rs b/rpc-router/src/tests.rs new file mode 100644 index 0000000..9a9f1e3 --- /dev/null +++ b/rpc-router/src/tests.rs @@ -0,0 +1,135 @@ +use super::*; + +fn zebra_schema() -> Value { + json!({ + "openrpc": "1.2.6", + "methods": [ + { "name": "getblock", "params": [] }, + { "name": "getinfo", "params": [] } + ], + "components": { + "schemas": { + "BlockHash": { "type": "string" } + } + } + }) +} + +fn zallet_schema() -> Value { + json!({ + "openrpc": "1.2.6", + "methods": [ + { "name": "getwalletinfo", "params": [] }, + { "name": "z_sendmany", "params": [] } + ], + "components": { + "schemas": { + "WalletInfo": { "type": "object" } + } + } + }) +} + +// --- extract_methods_array --- + +#[test] +fn test_extract_methods_array_returns_methods() { + let schema = zebra_schema(); + let methods = extract_methods_array(&schema); + assert_eq!(methods.len(), 2); + assert_eq!(methods[0]["name"], "getblock"); + assert_eq!(methods[1]["name"], "getinfo"); +} + +#[test] +fn test_extract_methods_array_missing_key_returns_empty() { + let schema = json!({ "openrpc": "1.2.6" }); + let methods = extract_methods_array(&schema); + assert!(methods.is_empty()); +} + +// --- annotate_methods_with_server --- + +#[test] +fn test_annotate_methods_sets_x_server() { + let mut methods = extract_methods_array(&zebra_schema()); + annotate_methods_with_server(&mut methods, "zebra"); + for m in &methods { + assert_eq!(m["x-server"], "zebra"); + } +} + +#[test] +fn test_annotate_methods_non_object_entry_does_not_panic() { + // A schema that contains a non-object method entry (e.g. a bare string). + let schema = json!({ "methods": ["not-an-object", { "name": "getblock" }] }); + let mut methods = extract_methods_array(&schema); + // Must not panic — the non-object entry is silently skipped. + annotate_methods_with_server(&mut methods, "zebra"); + assert_eq!(methods[1]["x-server"], "zebra"); +} + +// --- merge_components_schemas --- + +#[test] +fn test_merge_components_schemas_combines_keys() { + let mut combined = serde_json::Map::new(); + merge_components_schemas(&zebra_schema(), &mut combined); + merge_components_schemas(&zallet_schema(), &mut combined); + assert!(combined.contains_key("BlockHash")); + assert!(combined.contains_key("WalletInfo")); +} + +#[test] +fn test_merge_components_schemas_missing_components_is_noop() { + let schema = json!({ "methods": [] }); + let mut combined = serde_json::Map::new(); + merge_components_schemas(&schema, &mut combined); + assert!(combined.is_empty()); +} + +#[test] +fn test_merge_components_schemas_last_write_wins_on_conflict() { + let schema_a = json!({ "components": { "schemas": { "Foo": { "type": "string" } } } }); + let schema_b = json!({ "components": { "schemas": { "Foo": { "type": "integer" } } } }); + let mut combined = serde_json::Map::new(); + merge_components_schemas(&schema_a, &mut combined); + merge_components_schemas(&schema_b, &mut combined); + assert_eq!(combined["Foo"]["type"], "integer"); +} + +// --- merge_openrpc_schemas --- + +#[test] +fn test_merge_openrpc_schemas_combined_method_count() { + let z3 = merge_openrpc_schemas(zebra_schema(), zallet_schema()).unwrap(); + assert_eq!(z3.zebra_methods.len(), 2); + assert_eq!(z3.zallet_methods.len(), 2); + assert_eq!(z3.merged["methods"].as_array().unwrap().len(), 4); +} + +#[test] +fn test_merge_openrpc_schemas_methods_annotated() { + let z3 = merge_openrpc_schemas(zebra_schema(), zallet_schema()).unwrap(); + for m in &z3.zebra_methods { + assert_eq!(m["x-server"], "zebra"); + } + for m in &z3.zallet_methods { + assert_eq!(m["x-server"], "zallet"); + } +} + +#[test] +fn test_merge_openrpc_schemas_components_merged() { + let z3 = merge_openrpc_schemas(zebra_schema(), zallet_schema()).unwrap(); + let schemas = &z3.merged["components"]["schemas"]; + assert!(schemas.get("BlockHash").is_some()); + assert!(schemas.get("WalletInfo").is_some()); +} + +#[test] +fn test_merge_openrpc_schemas_info_fields_present() { + let z3 = merge_openrpc_schemas(zebra_schema(), zallet_schema()).unwrap(); + assert!(z3.merged["info"]["title"].is_string()); + assert!(z3.merged["info"]["version"].is_string()); +} From db2e279f8db8c67a60a3754c0f68bf9987691683 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:25:55 -0300 Subject: [PATCH 10/27] simplify --- rpc-router/src/main.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index e8c1023..154ac6d 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -175,17 +175,17 @@ async fn handler( )); } - if let Some(_method) = z3 + if z3 .zebra_methods .iter() - .find(|m| m["name"] == rpc_req.method) + .any(|m| m["name"] == rpc_req.method) { info!("Routing {} to Zebra", rpc_req.method); &config.zebra_url - } else if let Some(_method) = z3 + } else if z3 .zallet_methods .iter() - .find(|m| m["name"] == rpc_req.method) + .any(|m| m["name"] == rpc_req.method) { info!("Routing {} to Zallet", rpc_req.method); &config.zallet_url @@ -305,12 +305,7 @@ fn merge_openrpc_schemas(zebra: Value, zallet: Value) -> Result { let z3 = Z3Schema { zebra_methods, zallet_methods, - merged: Value::Object( - merged - .as_object() - .expect("merged object should be valid") - .clone(), - ), + merged, }; Ok(z3) From 77aa77e41e902d0e0b4943c8cb6f833edc6b7d48 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:32:49 -0300 Subject: [PATCH 11/27] rpc-router: read RPC credentials from env vars instead of hardcoding Read RPC_USER and RPC_PASSWORD from environment variables (defaulting to "zebra" for local dev). Pass credentials through Config into both forward_request and call_rpc_discover, removing the two hardcoded "zebra:zebra" literals. Add Config::from_env tests to verify default and custom credentials. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rpc-router/src/main.rs | 18 ++++++++++++------ rpc-router/src/tests.rs | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 154ac6d..721db9c 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -37,6 +37,8 @@ struct Config { zebra_url: String, zallet_url: String, zaino_url: String, + rpc_user: String, + rpc_password: String, } impl Config { @@ -47,6 +49,8 @@ impl Config { zallet_url: env::var("ZALLET_URL") .unwrap_or_else(|_| "http://127.0.0.1:25251".to_string()), zaino_url: env::var("ZAINO_URL").unwrap_or_else(|_| "http://zaino:8237".to_string()), + rpc_user: env::var("RPC_USER").unwrap_or_else(|_| "zebra".to_string()), + rpc_password: env::var("RPC_PASSWORD").unwrap_or_else(|_| "zebra".to_string()), } } } @@ -63,6 +67,8 @@ struct Z3Schema { async fn forward_request( req: Request>, target_url: &str, + rpc_user: &str, + rpc_password: &str, ) -> Result>> { let client = HyperClient::builder(TokioExecutor::new()).build_http(); @@ -83,7 +89,7 @@ async fn forward_request( .version(parts.version); // Inject auth header - let auth = general_purpose::STANDARD.encode("zebra:zebra"); + let auth = general_purpose::STANDARD.encode(format!("{}:{}", rpc_user, rpc_password)); new_req = new_req.header( hyper::header::AUTHORIZATION, hyper::header::HeaderValue::from_str(&format!("Basic {}", auth))?, @@ -201,7 +207,7 @@ async fn handler( // Reconstruct request with buffered body let new_req = Request::from_parts(parts, Full::new(body_bytes)); - match forward_request(new_req, target_url).await { + match forward_request(new_req, target_url, &config.rpc_user, &config.rpc_password).await { Ok(res) => Ok(add_cors_headers(res)), Err(e) => { error!("Forwarding error: {}", e); @@ -215,7 +221,7 @@ async fn handler( } /// Calls rpc.discover on the given URL and returns the parsed JSON response. -async fn call_rpc_discover(url: &str) -> Result { +async fn call_rpc_discover(url: &str, rpc_user: &str, rpc_password: &str) -> Result { let client = ReqwestClient::new(); let body = json!({ @@ -227,7 +233,7 @@ async fn call_rpc_discover(url: &str) -> Result { let text = client .post(url) - .basic_auth("zebra", Some("zebra")) + .basic_auth(rpc_user, Some(rpc_password)) .header(reqwest::header::CONTENT_TYPE, "application/json") .body(body.to_string()) .send() @@ -318,8 +324,8 @@ async fn main() -> Result<()> { let config = Arc::new(Config::from_env()); let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); - let zebra_schema = call_rpc_discover(&config.zebra_url).await?["result"].clone(); - let zallet_schema = call_rpc_discover(&config.zallet_url).await?["result"].clone(); + let zebra_schema = call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password).await?["result"].clone(); + let zallet_schema = call_rpc_discover(&config.zallet_url, &config.rpc_user, &config.rpc_password).await?["result"].clone(); let z3 = merge_openrpc_schemas(zebra_schema, zallet_schema)?; diff --git a/rpc-router/src/tests.rs b/rpc-router/src/tests.rs index 9a9f1e3..7b35ba3 100644 --- a/rpc-router/src/tests.rs +++ b/rpc-router/src/tests.rs @@ -133,3 +133,25 @@ fn test_merge_openrpc_schemas_info_fields_present() { assert!(z3.merged["info"]["title"].is_string()); assert!(z3.merged["info"]["version"].is_string()); } + +// --- Config::from_env --- + +#[test] +fn test_config_from_env_uses_defaults() { + env::remove_var("RPC_USER"); + env::remove_var("RPC_PASSWORD"); + let config = Config::from_env(); + assert_eq!(config.rpc_user, "zebra"); + assert_eq!(config.rpc_password, "zebra"); +} + +#[test] +fn test_config_from_env_reads_rpc_credentials() { + env::set_var("RPC_USER", "alice"); + env::set_var("RPC_PASSWORD", "s3cr3t"); + let config = Config::from_env(); + assert_eq!(config.rpc_user, "alice"); + assert_eq!(config.rpc_password, "s3cr3t"); + env::remove_var("RPC_USER"); + env::remove_var("RPC_PASSWORD"); +} From d854925600125c5011de8aa32d9ae37a00495189 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:39:04 -0300 Subject: [PATCH 12/27] rpc-router: make CORS origin configurable via CORS_ORIGIN env var Replace the hardcoded playground origin with a CORS_ORIGIN environment variable (defaulting to https://playground.open-rpc.org for dev). Document the new variable and production hardening note in the README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rpc-router/README.md | 8 ++++++++ rpc-router/src/main.rs | 17 +++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/rpc-router/README.md b/rpc-router/README.md index 80f140b..e8e24f3 100644 --- a/rpc-router/README.md +++ b/rpc-router/README.md @@ -109,3 +109,11 @@ http://localhost:8080/ ``` The RPC router automatically sets the required CORS headers, allowing the playground (or other browser-based tools) to call the local endpoint directly. + +By default the `Access-Control-Allow-Origin` header is set to `https://playground.open-rpc.org`. To allow a different origin (e.g. a dApp frontend or any browser client), set the `CORS_ORIGIN` environment variable: + +```bash +CORS_ORIGIN=https://myapp.example.com cargo run +``` + +For local development you can use `CORS_ORIGIN=*` to allow all origins. Avoid using `*` in production as it allows any website to call your local node. diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 721db9c..23f52fe 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -39,6 +39,7 @@ struct Config { zaino_url: String, rpc_user: String, rpc_password: String, + cors_origin: String, } impl Config { @@ -51,6 +52,8 @@ impl Config { zaino_url: env::var("ZAINO_URL").unwrap_or_else(|_| "http://zaino:8237".to_string()), rpc_user: env::var("RPC_USER").unwrap_or_else(|_| "zebra".to_string()), rpc_password: env::var("RPC_PASSWORD").unwrap_or_else(|_| "zebra".to_string()), + cors_origin: env::var("CORS_ORIGIN") + .unwrap_or_else(|_| "https://playground.open-rpc.org".to_string()), } } } @@ -113,13 +116,13 @@ async fn forward_request( } /// Adds CORS headers to the response. -fn add_cors_headers(mut resp: Response>) -> Response> { +fn add_cors_headers(mut resp: Response>, cors_origin: &str) -> Response> { let headers = resp.headers_mut(); + headers.insert( + HeaderName::from_static("access-control-allow-origin"), + HeaderValue::from_str(cors_origin).unwrap_or(HeaderValue::from_static("*")), + ); for &(name, value) in &[ - ( - "access-control-allow-origin", - "https://playground.open-rpc.org", - ), ("access-control-allow-methods", "POST, OPTIONS"), ("access-control-allow-headers", "Content-Type"), ("access-control-max-age", "86400"), @@ -151,6 +154,7 @@ async fn handler( .status(StatusCode::NO_CONTENT) .body(Full::new(Bytes::new())) .unwrap(), + &config.cors_origin, ); return Ok(resp); } @@ -178,6 +182,7 @@ async fn handler( .header(hyper::header::CONTENT_TYPE, "application/json") .body(Full::new(Bytes::from(serde_json::to_string(&z3.merged)?))) .expect("z3 merged schema response should be valid"), + &config.cors_origin, )); } @@ -208,7 +213,7 @@ async fn handler( let new_req = Request::from_parts(parts, Full::new(body_bytes)); match forward_request(new_req, target_url, &config.rpc_user, &config.rpc_password).await { - Ok(res) => Ok(add_cors_headers(res)), + Ok(res) => Ok(add_cors_headers(res, &config.cors_origin)), Err(e) => { error!("Forwarding error: {}", e); From ead7bb5d3e551669e3f9c0e87391d301d44943f2 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:40:48 -0300 Subject: [PATCH 13/27] change info to wanr --- rpc-router/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 23f52fe..74f1d44 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -201,7 +201,10 @@ async fn handler( info!("Routing {} to Zallet", rpc_req.method); &config.zallet_url } else { - info!("Routing {} to Zaino", rpc_req.method); + warn!( + "Method '{}' not found in Zebra or Zallet schema, falling back to Zaino", + rpc_req.method + ); &config.zaino_url } } else { From 755fda47288ae26f6e2c8adc2ca05005d63b97fb Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:50:50 -0300 Subject: [PATCH 14/27] rpc-router: document fail-fast startup behavior in README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rpc-router/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc-router/README.md b/rpc-router/README.md index e8e24f3..af613b2 100644 --- a/rpc-router/README.md +++ b/rpc-router/README.md @@ -18,7 +18,7 @@ In addition to request routing, the router also: ## Developer Usage -To run the router, Zebra and Zallet must already be running and listening on known ports. +To run the router, Zebra and Zallet must already be running, fully synced, and responsive on known ports **before** starting the router. At startup the router calls `rpc.discover` on both backends to build the merged schema — if either is unreachable the router exits immediately with an error. The router accepts this configuration via environment variables, or alternatively you can modify the values directly in main.rs. From f058faa20c342d463cbf5a69a9af5c4a210d0f9b Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 08:56:36 -0300 Subject: [PATCH 15/27] rpc-router: extract playground URL constant and document z3_merged.json staleness Extract the long playground URL into a PLAYGROUND_URL constant to keep main() readable. Add a README note explaining that the committed z3_merged.json is regenerated at startup and may go stale when Zebra or Zallet schemas change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rpc-router/README.md | 2 ++ rpc-router/src/main.rs | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rpc-router/README.md b/rpc-router/README.md index af613b2..aa44469 100644 --- a/rpc-router/README.md +++ b/rpc-router/README.md @@ -16,6 +16,8 @@ In addition to request routing, the router also: - Exposes the merged schema via its own `rpc.discover` method - Saves the merged schema to a local `z3_merged.json` file on startup +> **Note:** `z3_merged.json` is regenerated every time the router starts and the committed copy is used only to back the playground link in this README. It will go stale if Zebra or Zallet change their schemas — regenerate it by running the router against up-to-date backends and committing the new file. + ## Developer Usage To run the router, Zebra and Zallet must already be running, fully synced, and responsive on known ports **before** starting the router. At startup the router calls `rpc.discover` on both backends to build the merged schema — if either is unreachable the router exits immediately with an error. diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 74f1d44..9da47ec 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -5,6 +5,8 @@ //! to determine which methods belong to which service. use std::{env, net::SocketAddr, sync::Arc}; +const PLAYGROUND_URL: &str = "https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"; + use anyhow::Result; use base64::{engine::general_purpose, Engine as _}; use http_body_util::{BodyExt, Full}; @@ -345,7 +347,7 @@ async fn main() -> Result<()> { info!("RPC Router listening on {}", addr); info!("You can use the following playground URL:"); - info!("https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"); + info!("{}", PLAYGROUND_URL); loop { let (stream, _) = listener.accept().await?; From bf02219aaff97b8a421dbef9f7afc6d4c17a543b Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 09:16:09 -0300 Subject: [PATCH 16/27] rpc-router: add integration tests with mock backends Extract the accept loop into a run() function to make the router startable on a random port from tests. Add httpmock as a dev-dependency and src/integration_tests.rs covering health check, CORS preflight, rpc.discover schema merging, Zebra/Zallet/Zaino routing, and 405 for non-POST requests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rpc-router/Cargo.lock | 848 ++++++++++++++++++++++++++-- rpc-router/Cargo.toml | 5 +- rpc-router/src/integration_tests.rs | 283 ++++++++++ rpc-router/src/main.rs | 9 +- 4 files changed, 1109 insertions(+), 36 deletions(-) create mode 100644 rpc-router/src/integration_tests.rs diff --git a/rpc-router/Cargo.lock b/rpc-router/Cargo.lock index 0033c4d..77dc051 100644 --- a/rpc-router/Cargo.lock +++ b/rpc-router/Cargo.lock @@ -17,24 +17,275 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[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 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener 5.4.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-object-pool" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "333c456b97c3f2d50604e8b2624253b7f787208cb72eb75e64b0ad11b221652c" +dependencies = [ + "async-std", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel 2.5.0", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.4.1", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-std" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" +dependencies = [ + "async-attributes", + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "basic-cookies" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67bd8fd42c16bdb08688243dc5f0cc117a3ca9efeeaba3a345a18a6159ad96f7" +dependencies = [ + "lalrpop", + "lalrpop-util", + "regex", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel 2.5.0", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -63,6 +314,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -79,6 +339,39 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -87,7 +380,22 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "ena" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" +dependencies = [ + "log", ] [[package]] @@ -115,6 +423,33 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener 5.4.1", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -127,6 +462,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fnv" version = "1.0.7" @@ -172,6 +513,36 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -191,9 +562,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", + "futures-macro", "futures-task", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -219,6 +592,18 @@ dependencies = [ "wasip2", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.4.12" @@ -230,7 +615,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.4.0", "indexmap", "slab", "tokio", @@ -244,6 +629,23 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.4.0" @@ -254,6 +656,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -261,7 +674,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.4.0", ] [[package]] @@ -272,8 +685,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -289,6 +702,57 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "httpmock" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ec9586ee0910472dec1a1f0f8acf52f0fdde93aea74d70d4a3107b4be0fd5b" +dependencies = [ + "assert-json-diff", + "async-object-pool", + "async-std", + "async-trait", + "base64 0.21.7", + "basic-cookies", + "crossbeam-utils", + "form_urlencoded", + "futures-util", + "hyper 0.14.32", + "lazy_static", + "levenshtein", + "log", + "regex", + "serde", + "serde_json", + "serde_regex", + "similar", + "tokio", + "url", +] + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.8.1" @@ -300,8 +764,8 @@ dependencies = [ "futures-channel", "futures-core", "h2", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -318,8 +782,8 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", - "hyper", + "http 1.4.0", + "hyper 1.8.1", "hyper-util", "rustls", "rustls-pki-types", @@ -336,7 +800,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-util", "native-tls", "tokio", @@ -350,19 +814,19 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", "futures-util", - "http", - "http-body", - "hyper", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.1", "system-configuration", "tokio", "tower-layer", @@ -499,6 +963,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -515,18 +988,73 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata", +] + [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "levenshtein" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" + [[package]] name = "libc" version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +[[package]] +name = "libredox" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +dependencies = [ + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -553,6 +1081,9 @@ name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +dependencies = [ + "value-bag", +] [[package]] name = "matchers" @@ -603,6 +1134,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -641,7 +1178,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -662,6 +1199,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.5" @@ -691,6 +1234,31 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project" version = "1.1.10" @@ -708,7 +1276,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -723,12 +1291,37 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -738,6 +1331,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro2" version = "1.0.103" @@ -771,6 +1370,29 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + [[package]] name = "regex-automata" version = "0.4.13" @@ -794,15 +1416,15 @@ version = "0.12.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "h2", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.8.1", "hyper-rustls", "hyper-tls", "hyper-util", @@ -847,9 +1469,10 @@ name = "rpc-router" version = "0.1.0" dependencies = [ "anyhow", - "base64", + "base64 0.22.1", "http-body-util", - "hyper", + "httpmock", + "hyper 1.8.1", "hyper-util", "reqwest", "serde", @@ -918,6 +1541,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.28" @@ -983,7 +1615,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -999,6 +1631,16 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" +dependencies = [ + "regex", + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1035,6 +1677,18 @@ dependencies = [ "libc", ] +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + [[package]] name = "slab" version = "0.4.11" @@ -1047,6 +1701,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.1" @@ -1063,12 +1727,35 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[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.111" @@ -1097,7 +1784,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1134,6 +1821,37 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "thread_local" version = "1.1.9" @@ -1143,6 +1861,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -1165,7 +1892,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.1", "tokio-macros", "windows-sys 0.61.2", ] @@ -1178,7 +1905,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1253,8 +1980,8 @@ dependencies = [ "bitflags", "bytes", "futures-util", - "http", - "http-body", + "http 1.4.0", + "http-body 1.0.1", "iri-string", "pin-project-lite", "tower 0.5.2", @@ -1294,7 +2021,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] [[package]] @@ -1348,6 +2075,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" @@ -1378,12 +2111,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -1453,7 +2202,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -1476,6 +2225,37 @@ dependencies = [ "wasm-bindgen", ] +[[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-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[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-link" version = "0.2.1" @@ -1698,7 +2478,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", "synstructure", ] @@ -1719,7 +2499,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", "synstructure", ] @@ -1759,5 +2539,5 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.111", ] diff --git a/rpc-router/Cargo.toml b/rpc-router/Cargo.toml index 3e4ee46..7019769 100644 --- a/rpc-router/Cargo.toml +++ b/rpc-router/Cargo.toml @@ -10,10 +10,13 @@ base64 = "0.22" http-body-util = "0.1" hyper = { version = "1.2", features = ["full"] } hyper-util = { version = "0.1", features = ["full"] } -reqwest = "0.12" +reqwest = { version = "0.12", features = ["json"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tokio = { version = "1.36", features = ["full"] } tower = { version = "0.4", features = ["util"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } + +[dev-dependencies] +httpmock = "0.7" diff --git a/rpc-router/src/integration_tests.rs b/rpc-router/src/integration_tests.rs new file mode 100644 index 0000000..1a8a508 --- /dev/null +++ b/rpc-router/src/integration_tests.rs @@ -0,0 +1,283 @@ +use httpmock::prelude::*; +use reqwest::Client; +use serde_json::{json, Value}; +use std::sync::Arc; +use tokio::net::TcpListener; + +use super::*; + +// --- Mock backend helpers --- + +/// Starts a mock Zebra backend that handles rpc.discover and method forwarding. +/// Returns a distinct "zebra-response" result so routing can be verified. +async fn start_zebra_mock() -> MockServer { + let server = MockServer::start_async().await; + + server + .mock_async(|when, then| { + when.method(POST).body_contains("rpc.discover"); + then.status(200).json_body(json!({ + "jsonrpc": "2.0", "id": 1, + "result": { + "openrpc": "1.2.6", + "info": { "title": "Zebra", "version": "1.0.0" }, + "methods": [ + { "name": "getblock", "params": [] }, + { "name": "getinfo", "params": [] } + ], + "components": { "schemas": { "BlockHash": { "type": "string" } } } + } + })); + }) + .await; + + server + .mock_async(|when, then| { + when.method(POST); + then.status(200) + .json_body(json!({ "jsonrpc": "2.0", "id": 1, "result": "zebra-response" })); + }) + .await; + + server +} + +/// Starts a mock Zallet backend that handles rpc.discover and method forwarding. +async fn start_zallet_mock() -> MockServer { + let server = MockServer::start_async().await; + + server + .mock_async(|when, then| { + when.method(POST).body_contains("rpc.discover"); + then.status(200).json_body(json!({ + "jsonrpc": "2.0", "id": 1, + "result": { + "openrpc": "1.2.6", + "info": { "title": "Zallet", "version": "1.0.0" }, + "methods": [ + { "name": "getwalletinfo", "params": [] }, + { "name": "z_sendmany", "params": [] } + ], + "components": { "schemas": { "WalletInfo": { "type": "object" } } } + } + })); + }) + .await; + + server + .mock_async(|when, then| { + when.method(POST); + then.status(200) + .json_body(json!({ "jsonrpc": "2.0", "id": 1, "result": "zallet-response" })); + }) + .await; + + server +} + +/// Starts a mock Zaino backend (generic fallback). +async fn start_zaino_mock() -> MockServer { + let server = MockServer::start_async().await; + + server + .mock_async(|when, then| { + when.method(POST); + then.status(200) + .json_body(json!({ "jsonrpc": "2.0", "id": 1, "result": "zaino-response" })); + }) + .await; + + server +} + +// --- Router startup helper --- + +struct RouterHandle { + pub port: u16, + task: tokio::task::JoinHandle<()>, +} + +impl Drop for RouterHandle { + fn drop(&mut self) { + self.task.abort(); + } +} + +async fn start_router(zebra_url: &str, zallet_url: &str, zaino_url: &str) -> RouterHandle { + let config = Arc::new(Config { + zebra_url: zebra_url.to_string(), + zallet_url: zallet_url.to_string(), + zaino_url: zaino_url.to_string(), + rpc_user: "zebra".to_string(), + rpc_password: "zebra".to_string(), + cors_origin: "*".to_string(), + }); + + let zebra_schema = + call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password) + .await + .unwrap()["result"] + .clone(); + let zallet_schema = + call_rpc_discover(&config.zallet_url, &config.rpc_user, &config.rpc_password) + .await + .unwrap()["result"] + .clone(); + let z3 = merge_openrpc_schemas(zebra_schema, zallet_schema).unwrap(); + + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + let port = listener.local_addr().unwrap().port(); + + let task = tokio::spawn(async move { + if let Err(e) = run(config, listener, z3).await { + eprintln!("Router error in test: {}", e); + } + }); + + // Let the router start accepting connections. + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + RouterHandle { port, task } +} + +// --- Tests --- + +#[tokio::test] +async fn test_health_check() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .get(format!("http://127.0.0.1:{}/health", router.port)) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 200); + assert_eq!(resp.text().await.unwrap(), "OK"); +} + +#[tokio::test] +async fn test_non_post_returns_405() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .get(format!("http://127.0.0.1:{}/", router.port)) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 405); +} + +#[tokio::test] +async fn test_cors_preflight_returns_204_with_headers() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .request( + reqwest::Method::OPTIONS, + format!("http://127.0.0.1:{}/", router.port), + ) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 204); + assert!(resp.headers().contains_key("access-control-allow-origin")); + assert!(resp.headers().contains_key("access-control-allow-methods")); +} + +#[tokio::test] +async fn test_rpc_discover_returns_merged_schema() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .post(format!("http://127.0.0.1:{}/", router.port)) + .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "rpc.discover", "params": [] })) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 200); + + let body: Value = resp.json().await.unwrap(); + let methods = body["methods"].as_array().unwrap(); + let names: Vec<&str> = methods + .iter() + .map(|m| m["name"].as_str().unwrap()) + .collect(); + + assert!(names.contains(&"getblock")); + assert!(names.contains(&"getinfo")); + assert!(names.contains(&"getwalletinfo")); + assert!(names.contains(&"z_sendmany")); +} + +#[tokio::test] +async fn test_zebra_method_routing() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .post(format!("http://127.0.0.1:{}/", router.port)) + .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "getblock", "params": [] })) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 200); + let body: Value = resp.json().await.unwrap(); + assert_eq!(body["result"], "zebra-response"); +} + +#[tokio::test] +async fn test_zallet_method_routing() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .post(format!("http://127.0.0.1:{}/", router.port)) + .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "getwalletinfo", "params": [] })) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 200); + let body: Value = resp.json().await.unwrap(); + assert_eq!(body["result"], "zallet-response"); +} + +#[tokio::test] +async fn test_unknown_method_falls_back_to_zaino() { + let zebra = start_zebra_mock().await; + let zallet = start_zallet_mock().await; + let zaino = start_zaino_mock().await; + let router = start_router(&zebra.base_url(), &zallet.base_url(), &zaino.base_url()).await; + + let resp = Client::new() + .post(format!("http://127.0.0.1:{}/", router.port)) + .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "z_getaddressforaccount", "params": [] })) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 200); + let body: Value = resp.json().await.unwrap(); + assert_eq!(body["result"], "zaino-response"); +} diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 9da47ec..1d6ab24 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -345,10 +345,14 @@ async fn main() -> Result<()> { let listener = TcpListener::bind(addr).await?; info!("RPC Router listening on {}", addr); - info!("You can use the following playground URL:"); info!("{}", PLAYGROUND_URL); + run(config, listener, z3).await +} + +/// Accepts connections and dispatches requests. Extracted for testability. +async fn run(config: Arc, listener: TcpListener, z3: Z3Schema) -> Result<()> { loop { let (stream, _) = listener.accept().await?; let io = TokioIo::new(stream); @@ -371,3 +375,6 @@ async fn main() -> Result<()> { #[cfg(test)] mod tests; + +#[cfg(test)] +mod integration_tests; From d8139253e15bf553ed0a00c4335d48c5ec79acf4 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 09:19:57 -0300 Subject: [PATCH 17/27] add serial test --- rpc-router/Cargo.lock | 53 +++++++++++++++++++++++++++++++++++++++++ rpc-router/Cargo.toml | 1 + rpc-router/src/tests.rs | 3 +++ 3 files changed, 57 insertions(+) diff --git a/rpc-router/Cargo.lock b/rpc-router/Cargo.lock index 77dc051..6803520 100644 --- a/rpc-router/Cargo.lock +++ b/rpc-router/Cargo.lock @@ -513,6 +513,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.32" @@ -1477,6 +1488,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "serial_test", "tokio", "tower 0.4.13", "tracing", @@ -1550,6 +1562,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.28" @@ -1565,6 +1586,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + [[package]] name = "security-framework" version = "2.11.1" @@ -1653,6 +1680,32 @@ dependencies = [ "serde", ] +[[package]] +name = "serial_test" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "sharded-slab" version = "0.1.7" diff --git a/rpc-router/Cargo.toml b/rpc-router/Cargo.toml index 7019769..5e39c9a 100644 --- a/rpc-router/Cargo.toml +++ b/rpc-router/Cargo.toml @@ -20,3 +20,4 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] } [dev-dependencies] httpmock = "0.7" +serial_test = "3" diff --git a/rpc-router/src/tests.rs b/rpc-router/src/tests.rs index 7b35ba3..ee67ceb 100644 --- a/rpc-router/src/tests.rs +++ b/rpc-router/src/tests.rs @@ -1,4 +1,5 @@ use super::*; +use serial_test::serial; fn zebra_schema() -> Value { json!({ @@ -137,6 +138,7 @@ fn test_merge_openrpc_schemas_info_fields_present() { // --- Config::from_env --- #[test] +#[serial] fn test_config_from_env_uses_defaults() { env::remove_var("RPC_USER"); env::remove_var("RPC_PASSWORD"); @@ -146,6 +148,7 @@ fn test_config_from_env_uses_defaults() { } #[test] +#[serial] fn test_config_from_env_reads_rpc_credentials() { env::set_var("RPC_USER", "alice"); env::set_var("RPC_PASSWORD", "s3cr3t"); From 51937a68ed54e990847b1e6103e5e2d2334ce803 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 09:21:30 -0300 Subject: [PATCH 18/27] rename tests to unit tests --- rpc-router/src/main.rs | 2 +- rpc-router/src/{tests.rs => unit_tests.rs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename rpc-router/src/{tests.rs => unit_tests.rs} (100%) diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 1d6ab24..bdb309b 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -374,7 +374,7 @@ async fn run(config: Arc, listener: TcpListener, z3: Z3Schema) -> Result } #[cfg(test)] -mod tests; +mod unit_tests; #[cfg(test)] mod integration_tests; diff --git a/rpc-router/src/tests.rs b/rpc-router/src/unit_tests.rs similarity index 100% rename from rpc-router/src/tests.rs rename to rpc-router/src/unit_tests.rs From 8d28403d0ab3d8b73fcedca4e5ea1b03417dbd2c Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 09:26:03 -0300 Subject: [PATCH 19/27] fix readme --- rpc-router/README.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/rpc-router/README.md b/rpc-router/README.md index aa44469..af0238b 100644 --- a/rpc-router/README.md +++ b/rpc-router/README.md @@ -26,30 +26,22 @@ The router accepts this configuration via environment variables, or alternativel ### Running Zebra and Zallet for Development -For development and testing purposes, a helper utility was added to Zebra as part of the QA testing framework. This utility spawns both Zebra and Zallet in regtest mode. - -You can start both servers by running: +The easiest way to get Zebra and Zallet running locally is via the Docker Compose stack at the root of this repository: ```bash -python3 qa/rpc-tests/openrpc.py +docker compose up -d zebra zallet ``` -Example output: - -```bash -Keeping the test alive for 7200 seconds... -Zebra running at http://localhost:18666/ -Zallet running at http://localhost:23666/ -``` +Wait until both services are healthy, then note the RPC ports from your `.env` file (or the defaults in `docker-compose.yml`) and pass them to the router. -These two endpoints are then used by the RPC router. +> **Note:** A `openrpc.py` QA helper that spawned Zebra and Zallet in regtest mode previously existed in the Zebra repository but was removed. It has not been ported to the [zcash/integration-tests](https://github.com/zcash/integration-tests) repository. ### Running the RPC Router ```bash RUST_LOG=info \ -ZEBRA_URL=http://localhost:18666/ \ -ZALLET_URL=http://localhost:23666/ \ +ZEBRA_URL=http://localhost:/ \ +ZALLET_URL=http://localhost:/ \ cargo run ``` From fa7d05b6ca3d1aa1d8b1c3f119c8268e44584e70 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 09:26:24 -0300 Subject: [PATCH 20/27] fmt --- rpc-router/src/integration_tests.rs | 13 +++++++------ rpc-router/src/main.rs | 26 +++++++++++++++++--------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/rpc-router/src/integration_tests.rs b/rpc-router/src/integration_tests.rs index 1a8a508..9dc4c4a 100644 --- a/rpc-router/src/integration_tests.rs +++ b/rpc-router/src/integration_tests.rs @@ -113,11 +113,10 @@ async fn start_router(zebra_url: &str, zallet_url: &str, zaino_url: &str) -> Rou cors_origin: "*".to_string(), }); - let zebra_schema = - call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password) - .await - .unwrap()["result"] - .clone(); + let zebra_schema = call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password) + .await + .unwrap()["result"] + .clone(); let zallet_schema = call_rpc_discover(&config.zallet_url, &config.rpc_user, &config.rpc_password) .await @@ -272,7 +271,9 @@ async fn test_unknown_method_falls_back_to_zaino() { let resp = Client::new() .post(format!("http://127.0.0.1:{}/", router.port)) - .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "z_getaddressforaccount", "params": [] })) + .json( + &json!({ "jsonrpc": "2.0", "id": 1, "method": "z_getaddressforaccount", "params": [] }), + ) .send() .await .unwrap(); diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index bdb309b..f894596 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -188,11 +188,7 @@ async fn handler( )); } - if z3 - .zebra_methods - .iter() - .any(|m| m["name"] == rpc_req.method) - { + if z3.zebra_methods.iter().any(|m| m["name"] == rpc_req.method) { info!("Routing {} to Zebra", rpc_req.method); &config.zebra_url } else if z3 @@ -231,7 +227,11 @@ async fn handler( } /// Calls rpc.discover on the given URL and returns the parsed JSON response. -async fn call_rpc_discover(url: &str, rpc_user: &str, rpc_password: &str) -> Result { +async fn call_rpc_discover( + url: &str, + rpc_user: &str, + rpc_password: &str, +) -> Result { let client = ReqwestClient::new(); let body = json!({ @@ -268,7 +268,10 @@ fn annotate_methods_with_server(methods: &mut Vec, server_name: &str) { if let Some(obj) = m.as_object_mut() { obj.insert("x-server".to_string(), json!(server_name)); } else { - warn!("Skipping non-object method entry while annotating for {}", server_name); + warn!( + "Skipping non-object method entry while annotating for {}", + server_name + ); } } } @@ -334,8 +337,13 @@ async fn main() -> Result<()> { let config = Arc::new(Config::from_env()); let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); - let zebra_schema = call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password).await?["result"].clone(); - let zallet_schema = call_rpc_discover(&config.zallet_url, &config.rpc_user, &config.rpc_password).await?["result"].clone(); + let zebra_schema = call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password) + .await?["result"] + .clone(); + let zallet_schema = + call_rpc_discover(&config.zallet_url, &config.rpc_user, &config.rpc_password).await? + ["result"] + .clone(); let z3 = merge_openrpc_schemas(zebra_schema, zallet_schema)?; From 1fa6c75364aa3b17d42707904784286be5615282 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 17:22:43 -0300 Subject: [PATCH 21/27] router: fix fallback routing + add LISTEN_PORT + regtest dev environment - Change unknown method fallback from Zaino to Zebra: Zebra's OpenRPC schema only lists a subset of its supported methods, so unrecognized methods should fall back to Zebra (the full node) rather than Zaino. - Add LISTEN_PORT env var (default 8080) to avoid conflicts with other services using that port (e.g. Zebra's health endpoint). - Add rpc-router/regtest/: self-contained Docker Compose environment for local end-to-end testing against Zebra + Zallet in regtest mode, with init.sh to bootstrap the wallet and README with usage instructions. - Update docker-compose.yml to support ZEBRA_MINING__MINER_ADDRESS env var (commented out in .env; only needed for regtest). - Revert production config files (.env, config/zallet.toml, docker-compose.override.yml) back to mainnet defaults. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .env | 5 +- config/zallet.toml | 25 ++---- docker-compose.override.yml | 29 ++++++ docker-compose.yml | 1 + rpc-router/regtest/README.md | 64 +++++++++++++ rpc-router/regtest/config/zallet.toml | 42 +++++++++ rpc-router/regtest/config/zallet_identity.txt | 3 + rpc-router/regtest/docker-compose.yml | 89 +++++++++++++++++++ rpc-router/regtest/init.sh | 67 ++++++++++++++ rpc-router/src/main.rs | 11 ++- 10 files changed, 315 insertions(+), 21 deletions(-) create mode 100644 docker-compose.override.yml create mode 100644 rpc-router/regtest/README.md create mode 100644 rpc-router/regtest/config/zallet.toml create mode 100644 rpc-router/regtest/config/zallet_identity.txt create mode 100644 rpc-router/regtest/docker-compose.yml create mode 100755 rpc-router/regtest/init.sh diff --git a/.env b/.env index 6c00304..41150b0 100644 --- a/.env +++ b/.env @@ -89,7 +89,7 @@ Z3_GRAFANA_DATA_PATH=grafana_data # Network name for all services (e.g., Mainnet, Testnet, Regtest) NETWORK_NAME=Mainnet # Globally enables RPC cookie authentication -ENABLE_COOKIE_AUTH=true +ENABLE_COOKIE_AUTH=false # In-container directory for the .cookie authentication file COOKIE_AUTH_FILE_DIR=/var/run/auth @@ -104,6 +104,9 @@ COMPOSE_PROFILES=monitoring # ============================================================================= # Zebra Configuration # ============================================================================= +# Zebra mining configuration (regtest miner address from zcash/integration-tests) +# Uncomment and set for regtest testing; leave unset for mainnet +# ZEBRA_MINING__MINER_ADDRESS=tmSRd1r8gs77Ja67Fw1JcdoXytxsyrLTPJm # Zebra logging (will be mapped to RUST_LOG in container) Z3_ZEBRA_RUST_LOG=info # Zebra tracing filter (config-rs format: ZEBRA_TRACING__FILTER) diff --git a/config/zallet.toml b/config/zallet.toml index 4792c45..c448eb4 100644 --- a/config/zallet.toml +++ b/config/zallet.toml @@ -4,50 +4,41 @@ # It does NOT connect to the standalone Zaino service (which is for gRPC clients). # For full configuration options, run: zallet example-config -[builder] -# Transaction builder settings - using defaults - [builder.limits] -# Transaction limits - using defaults +orchard_actions = 250 [consensus] # Network must match NETWORK_NAME in .env (Mainnet/Testnet) network = "main" [database] -# Wallet database - using defaults (wallet.db in datadir) [external] -# External settings - using defaults [features] -as_of_version = "0.1.0-alpha.1" +as_of_version = "0.0.0" [features.deprecated] -# No deprecated features enabled [features.experimental] -# No experimental features enabled [indexer] # Zallet's embedded Zaino indexer libraries connect to Zebra's JSON-RPC endpoint # to fetch blockchain data. The validator_address MUST point to Zebra (not the # standalone Zaino service). Service name 'zebra' and port from Z3_ZEBRA_RPC_PORT in .env validator_address = "zebra:18232" - -# Cookie authentication (matches Zebra's ENABLE_COOKIE_AUTH=true) -validator_cookie_auth = true -validator_cookie_path = "/var/run/auth/.cookie" +validator_user = "zebra" +validator_password = "zebra" [keystore] -# Age encryption identity file (mounted from ./config/zallet_identity.txt) encryption_identity = "identity.txt" [note_management] -# Note management - using defaults [rpc] -# RPC server configuration -# Bind address is set via ZALLET_RPC_BIND environment variable in docker-compose bind = ["0.0.0.0:28232"] timeout = 30 + +[[rpc.auth]] +user = "zebra" +pwhash = "eaa27c81df81f655e69bbe84026e733a$bb9f70d53decfeca863cb114f7b0fd5ae050c7ef885c3d5fa73d5bace6c14fea" diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..2ae97cd --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,29 @@ +# docker-compose.override.yml.example +# +# Development override for quick iteration without waiting for Zebra sync +# +# Usage: +# cp docker-compose.override.yml.example docker-compose.override.yml +# docker compose up -d +# +# This override changes Zebra's healthcheck from /ready to /healthy, +# allowing dependent services (Zaino, Zallet) to start immediately +# once Zebra has peer connections, without waiting for full sync. +# +# ⚠️ WARNING: Services may experience delays or errors while Zebra syncs +# ⚠️ Only use for development/testing, NOT production +# +# For production or production-like testing, follow the two-phase deployment: +# 1. docker compose up -d zebra # Sync Zebra first +# 2. docker compose up -d # Start full stack + +services: + zebra: + healthcheck: + # Use /healthy (has peers) instead of /ready (synced to tip) + # Allows Zaino and Zallet to start immediately + test: ["CMD-SHELL", "curl -sf http://127.0.0.1:8080/healthy || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s diff --git a/docker-compose.yml b/docker-compose.yml index 7da1022..ad87684 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -53,6 +53,7 @@ services: - ZEBRA_RPC__ENABLE_COOKIE_AUTH=${ENABLE_COOKIE_AUTH} - ZEBRA_RPC__COOKIE_DIR=${COOKIE_AUTH_FILE_DIR} - ZEBRA_METRICS__ENDPOINT_ADDR=${ZEBRA_METRICS__ENDPOINT_ADDR} + - ZEBRA_MINING__MINER_ADDRESS=${ZEBRA_MINING__MINER_ADDRESS} volumes: # Blockchain state (defaults to named volume 'zebra_data') - ${Z3_ZEBRA_DATA_PATH}:/home/zebra/.cache/zebra diff --git a/rpc-router/regtest/README.md b/rpc-router/regtest/README.md new file mode 100644 index 0000000..a459f48 --- /dev/null +++ b/rpc-router/regtest/README.md @@ -0,0 +1,64 @@ +# RPC Router — Regtest Environment + +Self-contained Docker Compose setup for local end-to-end testing of the rpc-router against real Zebra and Zallet backends in regtest mode. + +**Does not touch the production stack** in the repo root. + +## Prerequisites + +- Docker with the `z3-zallet:local` image built: + ```bash + cd ../../ # repo root + sudo docker compose build zallet + ``` + +## First-time setup + +```bash +cd rpc-router/regtest +./init.sh +``` + +This will: +1. Start Zebra in regtest mode +2. Mine 1 block (activates Orchard at height 1) +3. Initialize the Zallet wallet (`init-wallet-encryption` + `generate-mnemonic`) + +## Start the stack + +```bash +docker compose up -d +``` + +Router is available at **http://localhost:8181**. + +## Test routing + +```bash +# Route to Zebra (full node) +curl -s -X POST -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \ + http://localhost:8181 | jq . + +# Route to Zallet (wallet) +curl -s -X POST -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"getwalletinfo","params":[],"id":2}' \ + http://localhost:8181 | jq . + +# Merged OpenRPC schema +curl -s -X POST -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"rpc.discover","params":[],"id":3}' \ + http://localhost:8181 | jq .info.title +``` + +## Stop and clean up + +```bash +docker compose down -v # -v removes the regtest volumes +``` + +## Notes + +- Credentials: `zebra` / `zebra` (hardcoded for regtest only) +- Zallet uses regtest nuparams activating all upgrades at block 1 +- The rpc-router Dockerfile is in `rpc-router/` (one level up) diff --git a/rpc-router/regtest/config/zallet.toml b/rpc-router/regtest/config/zallet.toml new file mode 100644 index 0000000..cf11597 --- /dev/null +++ b/rpc-router/regtest/config/zallet.toml @@ -0,0 +1,42 @@ +[builder.limits] +orchard_actions = 250 + +[consensus] +network = "regtest" +regtest_nuparams = [ + "5ba81b19:1", + "76b809bb:1", + "2bb40e60:1", + "f5b9230b:1", + "e9ff75a6:1", +] + +[database] + +[external] + +[features] +as_of_version = "0.0.0" + +[features.deprecated] + +[features.experimental] + +[indexer] +validator_address = "zebra:18232" +validator_user = "zebra" +validator_password = "zebra" + +[keystore] +encryption_identity = "identity.txt" + +[note_management] + +[rpc] +bind = ["0.0.0.0:28232"] +timeout = 30 + +[[rpc.auth]] +user = "zebra" +# Password: "zebra" (from zcash/integration-tests) +pwhash = "eaa27c81df81f655e69bbe84026e733a$bb9f70d53decfeca863cb114f7b0fd5ae050c7ef885c3d5fa73d5bace6c14fea" diff --git a/rpc-router/regtest/config/zallet_identity.txt b/rpc-router/regtest/config/zallet_identity.txt new file mode 100644 index 0000000..558d28b --- /dev/null +++ b/rpc-router/regtest/config/zallet_identity.txt @@ -0,0 +1,3 @@ +# created: 2025-04-22T10:45:29-03:00 +# public key: age1l5d76x6zzsqy90r05a29gysjny7uvh229p5jnrwyqp5dmy39ha2qks3h9f +AGE-SECRET-KEY-1U7FJQWFKZYP7LJFJG9EVM6CG47P5TWP0NU03JE7CZQ6035H2JWDQKCRG65 diff --git a/rpc-router/regtest/docker-compose.yml b/rpc-router/regtest/docker-compose.yml new file mode 100644 index 0000000..47d178b --- /dev/null +++ b/rpc-router/regtest/docker-compose.yml @@ -0,0 +1,89 @@ +# docker-compose.yml for rpc-router regtest testing +# +# Runs Zebra + Zallet in regtest mode + the rpc-router. +# Completely self-contained; does not touch the production stack. +# +# Usage: +# cd rpc-router/regtest +# ./init.sh # first time: initialize wallet +# docker compose up -d +# # Router available at http://localhost:8181 +# # Test: curl -s -X POST -H "Content-Type: application/json" \ +# # -d '{"jsonrpc":"2.0","method":"getinfo","params":[],"id":1}' \ +# # http://localhost:8181 + +services: + zebra: + image: zfnd/zebra:3.1.0 + container_name: z3_regtest_zebra + restart: unless-stopped + environment: + - RUST_LOG=info + - ZEBRA_NETWORK__NETWORK=Regtest + - ZEBRA_RPC__LISTEN_ADDR=0.0.0.0:18232 + - ZEBRA_RPC__ENABLE_COOKIE_AUTH=false + - ZEBRA_MINING__MINER_ADDRESS=tmSRd1r8gs77Ja67Fw1JcdoXytxsyrLTPJm + - ZEBRA_HEALTH__LISTEN_ADDR=0.0.0.0:8080 + - ZEBRA_HEALTH__ENFORCE_ON_TEST_NETWORKS=false + - ZEBRA_STATE__CACHE_DIR=/home/zebra/.cache/zebra + volumes: + - zebra_regtest_data:/home/zebra/.cache/zebra + ports: + - "18232:18232" + networks: + - regtest_net + healthcheck: + # Regtest has no peers; check RPC port directly + test: ["CMD-SHELL", "curl -sf -X POST -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"method\":\"getblockchaininfo\",\"params\":[],\"id\":1}' http://127.0.0.1:18232 || exit 1"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + zallet: + image: z3-zallet:local + container_name: z3_regtest_zallet + restart: unless-stopped + user: "65532:65532" + command: ["--datadir", "/var/lib/zallet", "start"] + depends_on: + zebra: + condition: service_healthy + environment: + - RUST_LOG=info + volumes: + - zallet_regtest_data:/var/lib/zallet + - ./config/zallet.toml:/var/lib/zallet/zallet.toml:ro + - ./config/zallet_identity.txt:/var/lib/zallet/identity.txt:ro + ports: + - "28232:28232" + networks: + - regtest_net + + rpc-router: + build: + context: ../ + dockerfile: Dockerfile + container_name: z3_regtest_router + restart: unless-stopped + environment: + - ZEBRA_URL=http://z3_regtest_zebra:18232 + - ZALLET_URL=http://z3_regtest_zallet:28232 + - RPC_USER=zebra + - RPC_PASSWORD=zebra + - LISTEN_PORT=8181 + ports: + - "8181:8181" + depends_on: + zebra: + condition: service_healthy + networks: + - regtest_net + +volumes: + zebra_regtest_data: + zallet_regtest_data: + +networks: + regtest_net: + driver: bridge diff --git a/rpc-router/regtest/init.sh b/rpc-router/regtest/init.sh new file mode 100755 index 0000000..a81ea5d --- /dev/null +++ b/rpc-router/regtest/init.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# init.sh - Initialize the regtest wallet for the first time. +# +# Run this once before `docker compose up -d`. +# Safe to re-run: skips steps if already done. +# +# Requirements: +# - Docker with the z3-zallet:local image built (cd ../../ && docker compose build zallet) +# - No running z3_regtest_* containers + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +NETWORK=regtest_net +VOLUME=z3_regtest_zallet_data +ZALLET_IMAGE=z3-zallet:local + +cd "$SCRIPT_DIR" + +echo "==> Starting Zebra in regtest mode..." +docker compose up -d zebra + +echo "==> Waiting for Zebra RPC to be ready..." +until docker compose exec zebra curl -sf -X POST \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \ + http://127.0.0.1:18232 > /dev/null 2>&1; do + echo " Zebra not ready yet, retrying..." + sleep 2 +done +echo " Zebra is ready." + +echo "==> Mining 1 block (required for Orchard activation at height 1)..." +docker compose exec zebra curl -s -u zebra:zebra \ + -X POST -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"generate","params":[1],"id":1}' \ + http://127.0.0.1:18232 | grep -q '"result"' +echo " Block mined." + +echo "==> Fixing volume permissions..." +docker run --rm -v "${VOLUME}:/var/lib/zallet" --user root busybox \ + chown -R 65532:65532 /var/lib/zallet + +echo "==> Running init-wallet-encryption..." +docker run --rm \ + --network "${NETWORK}" \ + -v "${VOLUME}:/var/lib/zallet" \ + -v "${SCRIPT_DIR}/config/zallet.toml:/var/lib/zallet/zallet.toml:ro" \ + -v "${SCRIPT_DIR}/config/zallet_identity.txt:/var/lib/zallet/identity.txt:ro" \ + --user 65532:65532 \ + "${ZALLET_IMAGE}" \ + --datadir /var/lib/zallet init-wallet-encryption + +echo "==> Running generate-mnemonic..." +docker run --rm \ + --network "${NETWORK}" \ + -v "${VOLUME}:/var/lib/zallet" \ + -v "${SCRIPT_DIR}/config/zallet.toml:/var/lib/zallet/zallet.toml:ro" \ + -v "${SCRIPT_DIR}/config/zallet_identity.txt:/var/lib/zallet/identity.txt:ro" \ + --user 65532:65532 \ + "${ZALLET_IMAGE}" \ + --datadir /var/lib/zallet generate-mnemonic + +echo "" +echo "✅ Wallet initialized. Now run:" +echo " docker compose up -d" +echo " # Router will be available at http://localhost:8181" diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index f894596..506c5b0 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -42,6 +42,7 @@ struct Config { rpc_user: String, rpc_password: String, cors_origin: String, + listen_port: u16, } impl Config { @@ -56,6 +57,10 @@ impl Config { rpc_password: env::var("RPC_PASSWORD").unwrap_or_else(|_| "zebra".to_string()), cors_origin: env::var("CORS_ORIGIN") .unwrap_or_else(|_| "https://playground.open-rpc.org".to_string()), + listen_port: env::var("LISTEN_PORT") + .ok() + .and_then(|p| p.parse().ok()) + .unwrap_or(8080), } } } @@ -200,10 +205,10 @@ async fn handler( &config.zallet_url } else { warn!( - "Method '{}' not found in Zebra or Zallet schema, falling back to Zaino", + "Method '{}' not found in Zebra or Zallet schema, falling back to Zebra", rpc_req.method ); - &config.zaino_url + &config.zebra_url } } else { warn!("Failed to parse JSON-RPC body, defaulting to Zebra"); @@ -335,7 +340,7 @@ async fn main() -> Result<()> { tracing_subscriber::fmt::init(); let config = Arc::new(Config::from_env()); - let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); + let addr = SocketAddr::from(([0, 0, 0, 0], config.listen_port)); let zebra_schema = call_rpc_discover(&config.zebra_url, &config.rpc_user, &config.rpc_password) .await?["result"] From ff422ac0596af46de5db6f1817bfa072a36e2e89 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 17:22:55 -0300 Subject: [PATCH 22/27] zallet: bump submodule to fix regtest crash Update zallet submodule from 60b0235 to ae762c05 which upgrades zcash_client_sqlite to 0.19.3, fixing a panic in the orchard_shardtree migration on fresh regtest databases. Ref: https://github.com/zcash/wallet/commit/ae762c05 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- zallet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zallet b/zallet index 60b0235..ae762c0 160000 --- a/zallet +++ b/zallet @@ -1 +1 @@ -Subproject commit 60b0235f292268bdc9a91b004e1e61ed9a73c9e9 +Subproject commit ae762c05ed79916b785e62ecb8afa53d7f7bc416 From d626fb8408234ba67ba804464b1c84f006c5df72 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 17:49:59 -0300 Subject: [PATCH 23/27] update rust version --- rpc-router/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc-router/Dockerfile b/rpc-router/Dockerfile index 2365d82..50f7b00 100644 --- a/rpc-router/Dockerfile +++ b/rpc-router/Dockerfile @@ -1,4 +1,4 @@ -FROM lukemathwalker/cargo-chef:latest-rust-1.82 AS chef +FROM lukemathwalker/cargo-chef:latest-rust-1.85 AS chef WORKDIR /app FROM chef AS planner From 65c98032d1d8ce95e7a0dd6d4b5e1b7621b75de2 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 17:50:57 -0300 Subject: [PATCH 24/27] update regtest --- rpc-router/regtest/README.md | 34 ++++++++++++++++++----- rpc-router/regtest/docker-compose.yml | 1 - rpc-router/regtest/init.sh | 39 +++++++++------------------ 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/rpc-router/regtest/README.md b/rpc-router/regtest/README.md index a459f48..6107360 100644 --- a/rpc-router/regtest/README.md +++ b/rpc-router/regtest/README.md @@ -27,7 +27,7 @@ This will: ## Start the stack ```bash -docker compose up -d +sudo -E docker compose up -d ``` Router is available at **http://localhost:8181**. @@ -38,23 +38,23 @@ Router is available at **http://localhost:8181**. # Route to Zebra (full node) curl -s -X POST -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \ - http://localhost:8181 | jq . + http://127.0.0.1:8181 # Route to Zallet (wallet) curl -s -X POST -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"getwalletinfo","params":[],"id":2}' \ - http://localhost:8181 | jq . + http://127.0.0.1:8181 -# Merged OpenRPC schema +# Merged OpenRPC schema title curl -s -X POST -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"rpc.discover","params":[],"id":3}' \ - http://localhost:8181 | jq .info.title + http://127.0.0.1:8181 | grep -o '"title":"[^"]*"' ``` ## Stop and clean up ```bash -docker compose down -v # -v removes the regtest volumes +sudo -E docker compose down -v # -v removes the regtest volumes ``` ## Notes @@ -62,3 +62,25 @@ docker compose down -v # -v removes the regtest volumes - Credentials: `zebra` / `zebra` (hardcoded for regtest only) - Zallet uses regtest nuparams activating all upgrades at block 1 - The rpc-router Dockerfile is in `rpc-router/` (one level up) + +## Tested environment + +Successfully tested on: + +- **OS**: Linux Mint 21.2 (kernel 5.15.0-171-generic) +- **Rust**: 1.90.0 (rpc-router built locally; Docker image uses `rust-1.85`) +- **Docker Compose**: v5.1.0 (plugin, not standalone `docker-compose`) +- **Zallet image**: `z3-zallet:local` built from submodule at `ae762c05` (Feb 2026) +- **Zebra image**: `zfnd/zebra:3.1.0` + +Expected output for the test commands above: + +**`getwalletinfo`** → routed to Zallet: +```json +{"jsonrpc":"2.0","result":{"walletversion":0,"balance":0.00000000,"unconfirmed_balance":0.00000000,"immature_balance":0.00000000,"shielded_balance":"0.00","shielded_unconfirmed_balance":"0.00","txcount":0,"keypoololdest":0,"keypoolsize":0,"mnemonic_seedfp":"TODO"},"id":1} +``` + +**`getblockchaininfo`** → routed to Zebra (truncated): +```json +{"jsonrpc":"2.0","id":1,"result":{"chain":"test","blocks":1,"headers":1,...,"upgrades":{"5ba81b19":{"name":"Overwinter","activationheight":1,"status":"active"},...}}} +``` diff --git a/rpc-router/regtest/docker-compose.yml b/rpc-router/regtest/docker-compose.yml index 47d178b..3145c24 100644 --- a/rpc-router/regtest/docker-compose.yml +++ b/rpc-router/regtest/docker-compose.yml @@ -44,7 +44,6 @@ services: image: z3-zallet:local container_name: z3_regtest_zallet restart: unless-stopped - user: "65532:65532" command: ["--datadir", "/var/lib/zallet", "start"] depends_on: zebra: diff --git a/rpc-router/regtest/init.sh b/rpc-router/regtest/init.sh index a81ea5d..359aa12 100755 --- a/rpc-router/regtest/init.sh +++ b/rpc-router/regtest/init.sh @@ -11,17 +11,22 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -NETWORK=regtest_net -VOLUME=z3_regtest_zallet_data +NETWORK=regtest_regtest_net + +# Use sudo for docker if needed +DOCKER="docker" +if ! docker info > /dev/null 2>&1; then + DOCKER="sudo -E docker" +fi ZALLET_IMAGE=z3-zallet:local cd "$SCRIPT_DIR" echo "==> Starting Zebra in regtest mode..." -docker compose up -d zebra +$DOCKER compose up -d zebra echo "==> Waiting for Zebra RPC to be ready..." -until docker compose exec zebra curl -sf -X POST \ +until $DOCKER compose exec zebra curl -sf -X POST \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \ http://127.0.0.1:18232 > /dev/null 2>&1; do @@ -31,37 +36,19 @@ done echo " Zebra is ready." echo "==> Mining 1 block (required for Orchard activation at height 1)..." -docker compose exec zebra curl -s -u zebra:zebra \ +$DOCKER compose exec zebra curl -s -u zebra:zebra \ -X POST -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"generate","params":[1],"id":1}' \ http://127.0.0.1:18232 | grep -q '"result"' echo " Block mined." -echo "==> Fixing volume permissions..." -docker run --rm -v "${VOLUME}:/var/lib/zallet" --user root busybox \ - chown -R 65532:65532 /var/lib/zallet - echo "==> Running init-wallet-encryption..." -docker run --rm \ - --network "${NETWORK}" \ - -v "${VOLUME}:/var/lib/zallet" \ - -v "${SCRIPT_DIR}/config/zallet.toml:/var/lib/zallet/zallet.toml:ro" \ - -v "${SCRIPT_DIR}/config/zallet_identity.txt:/var/lib/zallet/identity.txt:ro" \ - --user 65532:65532 \ - "${ZALLET_IMAGE}" \ - --datadir /var/lib/zallet init-wallet-encryption +$DOCKER compose run --rm zallet --datadir /var/lib/zallet init-wallet-encryption echo "==> Running generate-mnemonic..." -docker run --rm \ - --network "${NETWORK}" \ - -v "${VOLUME}:/var/lib/zallet" \ - -v "${SCRIPT_DIR}/config/zallet.toml:/var/lib/zallet/zallet.toml:ro" \ - -v "${SCRIPT_DIR}/config/zallet_identity.txt:/var/lib/zallet/identity.txt:ro" \ - --user 65532:65532 \ - "${ZALLET_IMAGE}" \ - --datadir /var/lib/zallet generate-mnemonic +$DOCKER compose run --rm zallet --datadir /var/lib/zallet generate-mnemonic echo "" echo "✅ Wallet initialized. Now run:" -echo " docker compose up -d" +echo " sudo -E docker compose up -d" echo " # Router will be available at http://localhost:8181" From a889f108ec4a2477035edab429d07483e0e435c7 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 17:58:13 -0300 Subject: [PATCH 25/27] update cleanup instructions --- rpc-router/regtest/README.md | 6 +++++- rpc-router/regtest/init.sh | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/rpc-router/regtest/README.md b/rpc-router/regtest/README.md index 6107360..4629bc5 100644 --- a/rpc-router/regtest/README.md +++ b/rpc-router/regtest/README.md @@ -54,7 +54,11 @@ curl -s -X POST -H "Content-Type: application/json" \ ## Stop and clean up ```bash -sudo -E docker compose down -v # -v removes the regtest volumes +# Stop all containers (keeps volumes/wallet data) +sudo -E docker compose down + +# Stop and delete all volumes (full reset — re-run init.sh afterwards) +sudo -E docker compose down -v ``` ## Notes diff --git a/rpc-router/regtest/init.sh b/rpc-router/regtest/init.sh index 359aa12..e4b59fc 100755 --- a/rpc-router/regtest/init.sh +++ b/rpc-router/regtest/init.sh @@ -48,7 +48,10 @@ $DOCKER compose run --rm zallet --datadir /var/lib/zallet init-wallet-encryption echo "==> Running generate-mnemonic..." $DOCKER compose run --rm zallet --datadir /var/lib/zallet generate-mnemonic +echo "==> Stopping Zebra (will be restarted by docker compose up -d)..." +$DOCKER compose down + echo "" echo "✅ Wallet initialized. Now run:" echo " sudo -E docker compose up -d" -echo " # Router will be available at http://localhost:8181" +echo " # Router will be available at http://127.0.0.1:8181" From af088a2625a909261a5d2fbf6ab7457e278da48e Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 5 Mar 2026 19:26:18 -0300 Subject: [PATCH 26/27] remove static schema file generation --- rpc-router/README.md | 8 +- rpc-router/regtest/README.md | 10 +- rpc-router/regtest/init.sh | 16 +- rpc-router/src/integration_tests.rs | 1 + rpc-router/src/main.rs | 6 +- rpc-router/z3_merged.json | 3578 --------------------------- 6 files changed, 26 insertions(+), 3593 deletions(-) delete mode 100644 rpc-router/z3_merged.json diff --git a/rpc-router/README.md b/rpc-router/README.md index af0238b..76e516e 100644 --- a/rpc-router/README.md +++ b/rpc-router/README.md @@ -14,9 +14,6 @@ In addition to request routing, the router also: - Calls `rpc.discover` on both Zebra and Zallet at startup - Builds a merged OpenRPC schema for the Z3 stack - Exposes the merged schema via its own `rpc.discover` method -- Saves the merged schema to a local `z3_merged.json` file on startup - -> **Note:** `z3_merged.json` is regenerated every time the router starts and the committed copy is used only to back the playground link in this README. It will go stale if Zebra or Zallet change their schemas — regenerate it by running the router against up-to-date backends and committing the new file. ## Developer Usage @@ -48,7 +45,6 @@ cargo run Example output: ```bash -INFO rpc_router: Saved merged schema to z3_merged.json INFO rpc_router: RPC Router listening on 0.0.0.0:8080 INFO rpc_router: You can use the following playground URL: INFO rpc_router: https://playground.open-rpc.org/?... @@ -92,9 +88,9 @@ INFO rpc_router: Routing getwalletinfo to Zallet ### OpenRPC Playground -You can also interact with the merged OpenRPC schema using the OpenRPC Playground. The playground is configured to use the merged schema generated by the router. +You can interact with the merged OpenRPC schema using the OpenRPC Playground, pointed at your running router: -[Playground](https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false&uiSchema[appBar]) +[Playground](https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=http://127.0.0.1:8181&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false) When using the inspector, make sure the target server URL is set to: diff --git a/rpc-router/regtest/README.md b/rpc-router/regtest/README.md index 4629bc5..e45e56e 100644 --- a/rpc-router/regtest/README.md +++ b/rpc-router/regtest/README.md @@ -9,7 +9,7 @@ Self-contained Docker Compose setup for local end-to-end testing of the rpc-rout - Docker with the `z3-zallet:local` image built: ```bash cd ../../ # repo root - sudo docker compose build zallet + docker compose build zallet ``` ## First-time setup @@ -51,6 +51,14 @@ curl -s -X POST -H "Content-Type: application/json" \ http://127.0.0.1:8181 | grep -o '"title":"[^"]*"' ``` +## OpenRPC Playground + +Open the playground pointed at your locally running router: + +https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=http://127.0.0.1:8181&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false + +The playground will call `rpc.discover` on `http://127.0.0.1:8181` to load the live merged schema. + ## Stop and clean up ```bash diff --git a/rpc-router/regtest/init.sh b/rpc-router/regtest/init.sh index e4b59fc..a9b7d1d 100755 --- a/rpc-router/regtest/init.sh +++ b/rpc-router/regtest/init.sh @@ -43,10 +43,20 @@ $DOCKER compose exec zebra curl -s -u zebra:zebra \ echo " Block mined." echo "==> Running init-wallet-encryption..." -$DOCKER compose run --rm zallet --datadir /var/lib/zallet init-wallet-encryption +# Remove stale lock file if present (left by a previous interrupted run) +$DOCKER run --rm -v regtest_zallet_regtest_data:/data busybox \ + sh -c 'rm -f /data/.lock' +# Check if wallet already initialized by looking for the wallet database +ALREADY_INIT=$($DOCKER run --rm -v regtest_zallet_regtest_data:/data busybox \ + sh -c 'ls /data/*.sqlite /data/*.age 2>/dev/null | wc -l') +if [ "${ALREADY_INIT:-0}" -gt 0 ]; then + echo " Wallet already initialized, skipping." +else + $DOCKER compose run --rm zallet --datadir /var/lib/zallet init-wallet-encryption -echo "==> Running generate-mnemonic..." -$DOCKER compose run --rm zallet --datadir /var/lib/zallet generate-mnemonic + echo "==> Running generate-mnemonic..." + $DOCKER compose run --rm zallet --datadir /var/lib/zallet generate-mnemonic +fi echo "==> Stopping Zebra (will be restarted by docker compose up -d)..." $DOCKER compose down diff --git a/rpc-router/src/integration_tests.rs b/rpc-router/src/integration_tests.rs index 9dc4c4a..dd99141 100644 --- a/rpc-router/src/integration_tests.rs +++ b/rpc-router/src/integration_tests.rs @@ -108,6 +108,7 @@ async fn start_router(zebra_url: &str, zallet_url: &str, zaino_url: &str) -> Rou zebra_url: zebra_url.to_string(), zallet_url: zallet_url.to_string(), zaino_url: zaino_url.to_string(), + listen_port: 0, rpc_user: "zebra".to_string(), rpc_password: "zebra".to_string(), cors_origin: "*".to_string(), diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 506c5b0..775520a 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -5,7 +5,7 @@ //! to determine which methods belong to which service. use std::{env, net::SocketAddr, sync::Arc}; -const PLAYGROUND_URL: &str = "https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=https://raw.githubusercontent.com/oxarbitrage/z3/refs/heads/openrpc-router/rpc-router/z3_merged.json&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"; +const PLAYGROUND_URL: &str = "https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=http://127.0.0.1:8181&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"; use anyhow::Result; use base64::{engine::general_purpose, Engine as _}; @@ -352,10 +352,6 @@ async fn main() -> Result<()> { let z3 = merge_openrpc_schemas(zebra_schema, zallet_schema)?; - let file_path = "z3_merged.json"; - tokio::fs::write(file_path, serde_json::to_string_pretty(&z3.merged)?).await?; - info!("Saved merged schema to {}", file_path); - let listener = TcpListener::bind(addr).await?; info!("RPC Router listening on {}", addr); info!("You can use the following playground URL:"); diff --git a/rpc-router/z3_merged.json b/rpc-router/z3_merged.json deleted file mode 100644 index c580d7d..0000000 --- a/rpc-router/z3_merged.json +++ /dev/null @@ -1,3578 +0,0 @@ -{ - "components": { - "schemas": { - "Account": { - "description": "Information about the new account.", - "properties": { - "account": { - "description": "The new account's ZIP 32 account index.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "account_uuid": { - "description": "The new account's UUID within this Zallet instance.", - "type": "string" - } - }, - "required": [ - "account_uuid" - ], - "type": "object" - }, - "Account2": { - "properties": { - "account": { - "description": "The ZIP 32 account ID.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "account_uuid": { - "description": "The account's UUID within this Zallet instance.", - "type": "string" - }, - "addresses": { - "items": { - "$ref": "#/components/schemas/Address2" - }, - "type": "array" - } - }, - "required": [ - "account_uuid", - "addresses" - ], - "type": "object" - }, - "Account3": { - "properties": { - "account_uuid": { - "description": "The account's UUID within this Zallet instance.", - "type": "string" - }, - "seedfp": { - "type": "string" - }, - "zip32_account_index": { - "description": "The account's ZIP 32 account index.", - "format": "uint32", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "account_uuid", - "seedfp", - "zip32_account_index" - ], - "type": "object" - }, - "AccountEffect": { - "description": "The effect of a transaction on an account's balance.", - "properties": { - "delta": { - "description": "The net change of the account's balance, in ZEC.\n\nThis includes any contribution by this account to the transaction fee.", - "type": "number" - }, - "deltaZat": { - "description": "The net change of the account's balance, in zatoshis.\n\nThis includes any contribution by this account to the transaction fee.", - "format": "int64", - "type": "integer" - } - }, - "required": [ - "delta", - "deltaZat" - ], - "type": "object" - }, - "AccountParameter": { - "properties": { - "birthday_height": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "name": { - "type": "string" - }, - "seedfp": { - "type": "string" - }, - "zip32_account_index": { - "format": "uint32", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "name", - "seedfp", - "zip32_account_index", - "birthday_height" - ], - "type": "object" - }, - "Accounts": { - "description": "The list of recovered accounts.", - "properties": { - "accounts": { - "items": { - "$ref": "#/components/schemas/Account3" - }, - "type": "array" - } - }, - "required": [ - "accounts" - ], - "type": "object" - }, - "AddNodeCommand": { - "description": "Commands for the `addnode` RPC method.", - "oneOf": [ - { - "const": "add", - "description": "Add a node to the address book.", - "type": "string" - } - ] - }, - "Address": { - "description": "Information about a derived Unified Address.", - "properties": { - "account": { - "description": "The ZIP 32 account ID.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "account_uuid": { - "description": "The account's UUID within this Zallet instance.", - "type": "string" - }, - "address": { - "description": "The unified address corresponding to the diversifier.", - "type": "string" - }, - "diversifier_index": { - "description": "The diversifier index specified or chosen.", - "format": "uint128", - "minimum": 0, - "type": "integer" - }, - "receiver_types": { - "description": "The receiver types that the UA contains (valid values are \"p2pkh\", \"sapling\", \"orchard\").", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "account_uuid", - "diversifier_index", - "receiver_types", - "address" - ], - "type": "object" - }, - "Address2": { - "properties": { - "diversifier_index": { - "description": "A diversifier index used in the account.", - "format": "uint128", - "minimum": 0, - "type": "integer" - }, - "ua": { - "description": "The unified address corresponding to the diversifier.", - "type": "string" - } - }, - "required": [ - "diversifier_index", - "ua" - ], - "type": "object" - }, - "AddressSource": { - "properties": { - "derived_transparent": { - "description": "Each element in this list represents a set of transparent addresses derived from a\nsingle BIP 44 account index.", - "items": { - "$ref": "#/components/schemas/DerivedTransparentAddresses" - }, - "type": "array" - }, - "sapling": { - "description": "Each element in this list represents a set of diversified addresses derived from a\nsingle IVK.", - "items": { - "$ref": "#/components/schemas/SaplingAddresses" - }, - "type": "array" - }, - "source": { - "type": "string" - }, - "transparent": { - "anyOf": [ - { - "$ref": "#/components/schemas/TransparentAddresses" - }, - { - "type": "null" - } - ], - "description": "This object contains transparent addresses for which we have no derivation\ninformation." - }, - "unified": { - "description": "Each element in this list represents a set of diversified Unified Addresses\nderived from a single UFVK.", - "items": { - "$ref": "#/components/schemas/UnifiedAddresses" - }, - "type": "array" - } - }, - "required": [ - "source", - "derived_transparent", - "sapling", - "unified" - ], - "type": "object" - }, - "AmountParameter": { - "properties": { - "address": { - "description": "A taddr, zaddr, or Unified Address.", - "type": "string" - }, - "amount": { - "description": "The numeric amount in ZEC." - }, - "memo": { - "description": "If the address is a zaddr, raw data represented in hexadecimal string format. If\nthe output is being sent to a transparent address, it’s an error to include this\nfield.", - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "address", - "amount" - ], - "type": "object" - }, - "DerivedTransparentAddresses": { - "properties": { - "account": { - "description": "The BIP 44 account index.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "addresses": { - "items": { - "type": "string" - }, - "type": "array" - }, - "changeAddresses": { - "items": { - "type": "string" - }, - "type": "array" - }, - "ephemeralAddresses": { - "items": { - "type": "string" - }, - "type": "array" - }, - "seedfp": { - "type": "string" - } - }, - "required": [ - "seedfp", - "account", - "addresses", - "changeAddresses", - "ephemeralAddresses" - ], - "type": "object" - }, - "GetAddressBalanceRequest": { - "anyOf": [ - { - "description": "A list of address strings.", - "properties": { - "addresses": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "addresses" - ], - "type": "object" - }, - { - "description": "A single address string.", - "type": "string" - } - ], - "description": "A request for [`RpcServer::get_address_balance`]." - }, - "GetAddressTxIdsRequest": { - "anyOf": [ - { - "description": "A single address string.", - "type": "string" - }, - { - "description": "A full request object with address list and optional height range.", - "properties": { - "addresses": { - "description": "A list of addresses to get transactions from.", - "items": { - "type": "string" - }, - "type": "array" - }, - "end": { - "description": "The height to end looking for transactions.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "start": { - "description": "The height to start looking for transactions.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "addresses" - ], - "type": "object" - } - ], - "description": "Parameters of [`RpcServer::get_address_tx_ids`] RPC method.\n\nSee [`RpcServer::get_address_tx_ids`] for more details." - }, - "GetAddressUtxosRequest": { - "anyOf": [ - { - "description": "A single address string.", - "type": "string" - }, - { - "description": "A full request object with address list and chainInfo flag.", - "properties": { - "addresses": { - "description": "A list of addresses to get transactions from.", - "items": { - "type": "string" - }, - "type": "array" - }, - "chainInfo": { - "default": false, - "description": "The height to start looking for transactions.", - "type": "boolean" - } - }, - "required": [ - "addresses" - ], - "type": "object" - } - ], - "description": "Parameters of [`RpcServer::get_address_utxos`] RPC method." - }, - "GetBlockTemplateCapability": { - "description": "Valid `capabilities` values that indicate client-side support.", - "oneOf": [ - { - "const": "longpoll", - "description": "Long Polling support.\nCurrently ignored by zebra.", - "type": "string" - }, - { - "const": "coinbasetxn", - "description": "Information for coinbase transaction, default template data with the `coinbasetxn` field.\nCurrently ignored by zebra.", - "type": "string" - }, - { - "const": "coinbasevalue", - "description": "Coinbase value, template response provides a `coinbasevalue` field and omits `coinbasetxn` field.\nCurrently ignored by zebra.", - "type": "string" - }, - { - "const": "coinbaseaux", - "description": "Components of the coinbase transaction.\nCurrently ignored by zebra.", - "type": "string" - }, - { - "const": "proposal", - "description": "Currently ignored by zcashd and zebra.", - "type": "string" - }, - { - "const": "serverlist", - "description": "Currently ignored by zcashd and zebra.", - "type": "string" - }, - { - "const": "workid", - "description": "Currently ignored by zcashd and zebra.", - "type": "string" - }, - { - "const": "unknowncapability", - "description": "Unknown capability to fill in for mutations.", - "type": "string" - } - ] - }, - "GetBlockTemplateParameters": { - "description": "Optional parameter `jsonrequestobject` for `getblocktemplate` RPC request.\n\nThe `data` field must be provided in `proposal` mode, and must be omitted in `template` mode.\nAll other fields are optional.", - "properties": { - "capabilities": { - "description": "A list of client-side supported capability features", - "items": { - "$ref": "#/components/schemas/GetBlockTemplateCapability" - }, - "type": "array" - }, - "data": { - "anyOf": [ - { - "$ref": "#/components/schemas/HexData" - }, - { - "type": "null" - } - ], - "description": "Must be omitted when `getblocktemplate` RPC is called in \"template\" mode (or when `mode` is omitted).\nMust be provided when `getblocktemplate` RPC is called in \"proposal\" mode.\n\nHex-encoded block data to be validated and checked against the server's usual acceptance rules\n(excluding the check for a valid proof-of-work)." - }, - "longpollid": { - "anyOf": [ - { - "$ref": "#/components/schemas/LongPollId" - }, - { - "type": "null" - } - ], - "description": "An ID that delays the RPC response until the template changes.\n\nIn Zebra, the ID represents the chain tip, max time, and mempool contents." - }, - "mode": { - "$ref": "#/components/schemas/GetBlockTemplateRequestMode", - "default": "template", - "description": "Defines whether the RPC method should generate a block template or attempt to\nvalidate block data, checking against all of the server's usual acceptance rules\n(excluding the check for a valid proof-of-work)." - }, - "workid": { - "description": "The workid for the block template.\n\ncurrently unused.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "GetBlockTemplateRequestMode": { - "description": "Defines whether the RPC method should generate a block template or attempt to validate a block\nproposal.", - "oneOf": [ - { - "const": "template", - "description": "Indicates a request for a block template.", - "type": "string" - }, - { - "const": "proposal", - "description": "Indicates a request to validate block data.", - "type": "string" - } - ] - }, - "GetNotesCount": { - "description": "The number of notes in the wallet.", - "properties": { - "orchard": { - "description": "The number of Orchard notes in the wallet.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "sapling": { - "description": "The number of Sapling notes in the wallet.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "sprout": { - "description": "The number of Sprout notes in the wallet.\n\nAlways zero, because Sprout is not supported.", - "format": "uint32", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "sprout", - "sapling", - "orchard" - ], - "type": "object" - }, - "GetWalletInfo": { - "description": "The wallet state information.", - "properties": { - "balance": { - "description": "The total confirmed transparent balance of the wallet in ZEC.", - "minimum": 0, - "type": "number" - }, - "immature_balance": { - "description": "The total immature transparent balance of the wallet in ZEC.", - "minimum": 0, - "type": "number" - }, - "keypoololdest": { - "description": "The timestamp (seconds since GMT epoch) of the oldest pre-generated key in the\nkey pool.", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "keypoolsize": { - "description": "How many new keys are pre-generated.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "mnemonic_seedfp": { - "description": "The BLAKE2b-256 hash of the HD seed derived from the wallet's emergency recovery phrase.", - "type": "string" - }, - "shielded_balance": { - "description": "The total confirmed shielded balance of the wallet in ZEC.", - "type": "string" - }, - "shielded_unconfirmed_balance": { - "description": "The total unconfirmed shielded balance of the wallet in ZEC.\n\nNot included if `asOfHeight` is specified.", - "type": [ - "string", - "null" - ] - }, - "txcount": { - "description": "The total number of transactions in the wallet", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "unconfirmed_balance": { - "description": "The total unconfirmed transparent balance of the wallet in ZEC.\n\nNot included if `asOfHeight` is specified.", - "minimum": 0, - "type": [ - "number", - "null" - ] - }, - "unlocked_until": { - "description": "The timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is\nunlocked for transfers, or 0 if the wallet is locked.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "walletversion": { - "description": "The wallet version, in its \"Bitcoin client version\" form.", - "format": "uint64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "walletversion", - "balance", - "immature_balance", - "shielded_balance", - "txcount", - "keypoololdest", - "keypoolsize", - "mnemonic_seedfp" - ], - "type": "object" - }, - "HexData": { - "description": "Deserialize hex-encoded strings to bytes.", - "type": "string" - }, - "ListUnifiedReceivers": { - "description": "The receivers within a unified address.", - "properties": { - "orchard": { - "description": "A single-receiver Unified Address containing the Orchard receiver.", - "type": [ - "string", - "null" - ] - }, - "p2pkh": { - "description": "The legacy P2PKH transparent address.\n\nOmitted if `p2sh` is present.", - "type": [ - "string", - "null" - ] - }, - "p2sh": { - "description": "The legacy P2SH transparent address.\n\nOmitted if `p2pkh` is present.", - "type": [ - "string", - "null" - ] - }, - "sapling": { - "description": "The legacy Sapling address.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "LongPollId": { - "description": "The encoded long poll ID, generated from the [`LongPollInput`].\n\n`zcashd` IDs are currently 69 hex/decimal digits long.\nSince Zebra's IDs are only 46 hex/decimal digits, mining pools should be able to handle them.", - "type": "string" - }, - "NoteCommitmentSubtreeIndex": { - "description": "A note commitment subtree index, used to identify a subtree in a shielded pool.\nAlso used to count subtrees.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": "integer" - }, - "OpenRPC Schema": { - "$ref": "https://raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json" - }, - "OperationError": { - "properties": { - "code": { - "description": "Code", - "format": "int32", - "type": "integer" - }, - "data": { - "description": "Optional data", - "type": [ - "string", - "null" - ] - }, - "message": { - "description": "Message", - "type": "string" - } - }, - "required": [ - "code", - "message" - ], - "type": "object" - }, - "OperationId": { - "description": "An async operation ID.", - "type": "string" - }, - "OperationState": { - "description": "The possible states that an async operation can be in.", - "enum": [ - "Ready", - "Executing", - "Cancelled", - "Failed", - "Success" - ], - "type": "string" - }, - "OperationStatus": { - "description": "The status of an async operation.", - "properties": { - "creation_time": { - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "error": { - "anyOf": [ - { - "$ref": "#/components/schemas/OperationError" - }, - { - "type": "null" - } - ] - }, - "execution_secs": { - "description": "Execution time for successful operations.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "id": { - "$ref": "#/components/schemas/OperationId" - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "params": true, - "result": true, - "status": { - "$ref": "#/components/schemas/OperationState" - } - }, - "required": [ - "id", - "status", - "creation_time" - ], - "type": "object" - }, - "Orchard": { - "properties": { - "actions": { - "description": "The Orchard Actions for the transaction.", - "items": { - "$ref": "#/components/schemas/OrchardAction" - }, - "type": "array" - }, - "anchor": { - "description": "A root of the Orchard note commitment tree at some block height in the past,\nencoded as a hex string.\n\nOmitted if `actions` is empty.", - "type": [ - "string", - "null" - ] - }, - "bindingSig": { - "description": "An Orchard binding signature on the SIGHASH transaction hash, encoded as a hex\nstring.\n\nOmitted if `actions` is empty.", - "type": [ - "string", - "null" - ] - }, - "flags": { - "anyOf": [ - { - "$ref": "#/components/schemas/OrchardFlags" - }, - { - "type": "null" - } - ], - "description": "The Orchard bundle flags.\n\nOmitted if `actions` is empty." - }, - "proof": { - "description": "Encoding of aggregated zk-SNARK proofs for Orchard Actions, encoded as a hex\nstring.\n\nOmitted if `actions` is empty.", - "type": [ - "string", - "null" - ] - }, - "valueBalance": { - "description": "The net value of Orchard Actions in ZEC.", - "type": "number" - }, - "valueBalanceZat": { - "description": "The net value of Orchard Actions in zatoshis.", - "format": "int64", - "type": "integer" - } - }, - "required": [ - "actions", - "valueBalance", - "valueBalanceZat" - ], - "type": "object" - }, - "OrchardAction": { - "properties": { - "cmx": { - "description": "The x-coordinate of the note commitment for the output note, encoded as a hex\nstring.", - "type": "string" - }, - "cv": { - "description": "A value commitment to the net value of the input note minus the output note,\nencoded as a hex string.", - "type": "string" - }, - "encCiphertext": { - "description": "The output note encrypted to the recipient, encoded as a hex string.", - "type": "string" - }, - "ephemeralKey": { - "description": "An encoding of an ephemeral Pallas public key, encoded as a hex string.", - "type": "string" - }, - "nullifier": { - "description": "The nullifier of the input note, encoded as a hex string.", - "type": "string" - }, - "outCiphertext": { - "description": "A ciphertext enabling the sender to recover the output note, encoded as a hex\nstring.", - "type": "string" - }, - "rk": { - "description": "The randomized validating key for `spendAuthSig`, encoded as a hex string.", - "type": "string" - }, - "spendAuthSig": { - "description": "A signature authorizing the spend in this Action, encoded as a hex string.", - "type": "string" - } - }, - "required": [ - "cv", - "nullifier", - "rk", - "cmx", - "ephemeralKey", - "encCiphertext", - "outCiphertext", - "spendAuthSig" - ], - "type": "object" - }, - "OrchardFlags": { - "properties": { - "enableOutputs": { - "description": "Whether outputs are enabled in this Orchard bundle.", - "type": "boolean" - }, - "enableSpends": { - "description": "Whether spends are enabled in this Orchard bundle.", - "type": "boolean" - } - }, - "required": [ - "enableSpends", - "enableOutputs" - ], - "type": "object" - }, - "Output": { - "properties": { - "account_uuid": { - "description": "The UUID of the Zallet account that received the output.\n\nOmitted if the output is not for an account in the wallet (`outgoing = true`).", - "type": [ - "string", - "null" - ] - }, - "action": { - "description": "(orchard) the index of the action within the orchard bundle.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "address": { - "description": "The Zcash address that received the output.\n\nOmitted if this output was received on an account-internal address (e.g. change outputs),\nor is a transparent output to a script that is not either P2PKH or P2SH (and thus doesn't\nhave an address encoding).", - "type": [ - "string", - "null" - ] - }, - "memo": { - "description": "Hexadecimal string representation of the memo field.\n\nOmitted if this is a transparent output.", - "type": [ - "string", - "null" - ] - }, - "memoStr": { - "description": "UTF-8 string representation of memo field (if it contains valid UTF-8).\n\nOmitted if this is a transparent output.", - "type": [ - "string", - "null" - ] - }, - "outgoing": { - "description": "`true` if the output is not for an address in the wallet.", - "type": "boolean" - }, - "output": { - "description": "(sapling) the index of the output within the `vShieldedOutput`.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "pool": { - "description": "The value pool.\n\nOne of `[\"transparent\", \"sapling\", \"orchard\"]`.", - "type": "string" - }, - "tOut": { - "description": "(transparent) the index of the output within the `vout`.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "value": { - "description": "The value of the output in ZEC.", - "minimum": 0, - "type": "number" - }, - "valueZat": { - "description": "The value of the output in zatoshis.", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "walletInternal": { - "description": "`true` if the output was received by the account's internal viewing key.\n\nThe `address` field is guaranteed be absent when this field is set to `true`, in which case\nit indicates that this may be a change output, an output of a wallet-internal shielding\ntransaction, an output of a wallet-internal cross-account transfer, or otherwise is the\nresult of some wallet-internal operation.", - "type": "boolean" - } - }, - "required": [ - "pool", - "outgoing", - "walletInternal", - "value", - "valueZat" - ], - "type": "object" - }, - "PeerSocketAddr": { - "description": "A thin wrapper for [`SocketAddr`] which hides peer IP addresses in logs and metrics.", - "type": "string" - }, - "ResultType": { - "description": "Empty result indicating success.", - "type": "null" - }, - "ResultType10": { - "anyOf": [ - { - "description": "The serialized, hex-encoded data for `txid`.", - "type": "string" - }, - { - "$ref": "#/components/schemas/Transaction2", - "description": "An object describing the transaction in detail." - } - ], - "description": "The `getrawtransaction` response." - }, - "ResultType11": { - "description": "A list of address sources.", - "items": { - "$ref": "#/components/schemas/AddressSource" - }, - "type": "array" - }, - "ResultType2": { - "description": "The help response.", - "type": "string" - }, - "ResultType3": { - "description": "The stop response.", - "type": "null" - }, - "ResultType4": { - "description": "The relevant operations.", - "items": { - "$ref": "#/components/schemas/OperationStatus" - }, - "type": "array" - }, - "ResultType5": { - "description": "Empty result indicating success.", - "type": "null" - }, - "ResultType6": { - "description": "A list of transactions involving the wallet.", - "items": { - "$ref": "#/components/schemas/WalletTx" - }, - "type": "array" - }, - "ResultType7": { - "description": "A list of accounts.", - "items": { - "$ref": "#/components/schemas/Account2" - }, - "type": "array" - }, - "ResultType8": { - "description": "A list of operation IDs.", - "items": { - "$ref": "#/components/schemas/OperationId" - }, - "type": "array" - }, - "ResultType9": { - "description": "A list of unspent notes.", - "items": { - "$ref": "#/components/schemas/UnspentOutput" - }, - "type": "array" - }, - "SaplingAddresses": { - "properties": { - "addresses": { - "items": { - "type": "string" - }, - "type": "array" - }, - "zip32KeyPath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "addresses" - ], - "type": "object" - }, - "SaplingOutput": { - "properties": { - "cmu": { - "description": "The u-coordinate of the note commitment for the output note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "cv": { - "description": "Value commitment to the output note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "encCiphertext": { - "description": "The output note encrypted to the recipient, encoded as a hex string.", - "type": "string" - }, - "ephemeralKey": { - "description": "A Jubjub public key.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "outCiphertext": { - "description": "A ciphertext enabling the sender to recover the output note, encoded as a hex\nstring.", - "type": "string" - }, - "proof": { - "description": "A zero-knowledge proof using the Sapling Output circuit, encoded as a hex string.", - "type": "string" - } - }, - "required": [ - "cv", - "cmu", - "ephemeralKey", - "encCiphertext", - "outCiphertext", - "proof" - ], - "type": "object" - }, - "SaplingSpend": { - "properties": { - "anchor": { - "description": "Merkle root of the Sapling note commitment tree.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "cv": { - "description": "Value commitment to the input note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "nullifier": { - "description": "The nullifier of the input note.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "proof": { - "description": "A zero-knowledge proof using the Sapling Spend circuit, encoded as a hex string.", - "type": "string" - }, - "rk": { - "description": "The randomized public key for `spendAuthSig`.\n\nEncoded as a byte-reversed hex string for legacy reasons.", - "type": "string" - }, - "spendAuthSig": { - "description": "A signature authorizing this Spend, encoded as a hex string.", - "type": "string" - } - }, - "required": [ - "cv", - "anchor", - "nullifier", - "rk", - "proof", - "spendAuthSig" - ], - "type": "object" - }, - "Spend": { - "properties": { - "account_uuid": { - "description": "The UUID of the Zallet account that received the corresponding output.\n\nOmitted if the output is not for an account in the wallet (which always means that\n`pool` is `\"transparent\"`; external shielded spends are never included because\nthey are unviewable).", - "type": [ - "string", - "null" - ] - }, - "action": { - "description": "(orchard) the index of the action within orchard bundle.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "actionPrev": { - "description": "(orchard) the index of the corresponding action within the previous transaction's\nOrchard bundle.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "address": { - "description": "The Zcash address involved in the transaction.\n\nOmitted if this note was received on an account-internal address (e.g. change\nnotes).", - "type": [ - "string", - "null" - ] - }, - "outputPrev": { - "description": "(sapling) the index of the corresponding output within the previous transaction's\n`vShieldedOutput`.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "pool": { - "description": "The value pool.\n\nOne of `[\"transparent\", \"sapling\", \"orchard\"]`.", - "type": "string" - }, - "spend": { - "description": "(sapling) the index of the spend within `vShieldedSpend`.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "tIn": { - "description": "(transparent) the index of the spend within `vin`.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "tOutPrev": { - "description": "(transparent) the index of the corresponding output within the previous\ntransaction's `vout`.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "txidPrev": { - "description": "The id for the transaction this note was created in.", - "type": "string" - }, - "value": { - "description": "The amount in ZEC.", - "minimum": 0, - "type": "number" - }, - "valueZat": { - "description": "The amount in zatoshis.", - "format": "uint64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "pool", - "txidPrev", - "value", - "valueZat" - ], - "type": "object" - }, - "SubmitBlockParameters": { - "description": "Optional argument `jsonparametersobject` for `submitblock` RPC request\n\nSee the notes for the [`submit_block`](crate::methods::RpcServer::submit_block) RPC.", - "properties": { - "workid": { - "description": "The workid for the block template. Currently unused.\n\n> If the server provided a workid, it MUST be included with submissions,\n\nRationale:\n\n> If servers allow all mutations, it may be hard to identify which job it is based on.\n> While it may be possible to verify the submission by its content, it is much easier\n> to compare it to the job issued. It is very easy for the miner to keep track of this.\n> Therefore, using a \"workid\" is a very cheap solution to enable more mutations.\n\n", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "TotalBalance": { - "description": "The total value of funds stored in the wallet.", - "properties": { - "private": { - "description": "The total value of unspent Sapling and Orchard outputs, in ZEC", - "type": "string" - }, - "total": { - "description": "The total value of unspent shielded and transparent outputs, in ZEC", - "type": "string" - }, - "transparent": { - "description": "The total value of unspent transparent outputs, in ZEC", - "type": "string" - } - }, - "required": [ - "transparent", - "private", - "total" - ], - "type": "object" - }, - "Transaction": { - "description": "Detailed information about an in-wallet transaction.", - "properties": { - "accounts": { - "additionalProperties": { - "$ref": "#/components/schemas/AccountEffect" - }, - "description": "A map from an involved account's UUID to the effects of this transaction on it.", - "type": "object" - }, - "blockhash": { - "description": "The hash of the main chain block that this transaction is mined in.\n\nOmitted if this transaction is not mined within a block in the current best chain.", - "type": [ - "string", - "null" - ] - }, - "blockindex": { - "description": "The index of the transaction within its block's `vtx` field.\n\nOmitted if this transaction is not mined within a block in the current best chain.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "blocktime": { - "description": "The time in seconds since epoch (1 Jan 1970 GMT) that the main chain block\ncontaining this transaction was mined.\n\nOmitted if this transaction is not mined within a block in the current best chain.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "confirmations": { - "description": "The number of confirmations.\n\n- A positive value is the number of blocks that have been mined including the\n transaction in the chain. For example, 1 confirmation means the transaction is\n in the block currently at the chain tip.\n- 0 means the transaction is in the mempool. If `asOfHeight` was set, this case\n will not occur.\n- -1 means the transaction cannot be mined.", - "format": "int64", - "type": "integer" - }, - "expiryheight": { - "description": "The greatest height at which this transaction can be mined, or 0 if this\ntransaction does not expire.", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "fee": { - "description": "The fee paid by the transaction.\n\nOmitted if this is a coinbase transaction, or if the fee cannot be determined\nbecause one or more transparent inputs of the transaction cannot be found.", - "minimum": 0, - "type": [ - "number", - "null" - ] - }, - "generated": { - "description": "Set to `true` if this is a coinbase transaction, omitted otherwise.", - "type": [ - "boolean", - "null" - ] - }, - "outputs": { - "description": "The outputs of the transaction that the wallet is capable of viewing.", - "items": { - "$ref": "#/components/schemas/Output" - }, - "type": "array" - }, - "spends": { - "description": "The inputs to the transaction that the wallet is capable of viewing.", - "items": { - "$ref": "#/components/schemas/Spend" - }, - "type": "array" - }, - "status": { - "description": "The transaction status.\n\nOne of 'mined', 'waiting', 'expiringsoon' or 'expired'.", - "type": "string" - }, - "txid": { - "description": "The transaction ID.", - "type": "string" - }, - "version": { - "description": "The transaction version.", - "format": "uint32", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "txid", - "status", - "confirmations", - "version", - "expiryheight", - "spends", - "outputs", - "accounts" - ], - "type": "object" - }, - "Transaction2": { - "description": "Verbose information about a transaction.", - "properties": { - "authdigest": { - "description": "The transaction's authorizing data commitment.\n\nFor pre-v5 transactions this will be `ffff..ffff`.\n\nEncoded as a byte-reversed hex string to match `txid`.", - "type": "string" - }, - "bindingSig": { - "description": "The Sapling binding signature, encoded as a hex string.\n\nOmitted if `version < 4`, or both `vShieldedSpend` and `vShieldedOutput` are empty.", - "type": [ - "string", - "null" - ] - }, - "blockhash": { - "description": "The hash of the block that the transaction is mined in, if any.\n\nOmitted if the transaction is not known to be mined in any block.", - "type": [ - "string", - "null" - ] - }, - "blocktime": { - "description": "The block time in seconds since epoch (Jan 1 1970 GMT) for the block that the\ntransaction is mined in.\n\nOmitted if `blockhash` is either omitted or not in the current best chain.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "confirmations": { - "description": "The number of confirmations the transaction has, or 0 if the block it is mined in\nis not in the current best chain.\n\nOmitted if `blockhash` is either omitted or unknown.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "expiryheight": { - "description": "The block height after which the transaction expires.\n\nOmitted if `overwintered` is `false`.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "height": { - "description": "The height of the block that the transaction is mined in, or -1 if that block is\nnot in the current best chain.\n\nOmitted if `blockhash` is either omitted or unknown.", - "format": "int32", - "type": [ - "integer", - "null" - ] - }, - "hex": { - "description": "The serialized, hex-encoded data for the transaction identified by `txid`.", - "type": "string" - }, - "in_active_chain": { - "description": "Whether specified block is in the active chain or not.\n\nOnly present with explicit `blockhash` argument.", - "type": [ - "boolean", - "null" - ] - }, - "locktime": { - "description": "The lock time.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "orchard": { - "anyOf": [ - { - "$ref": "#/components/schemas/Orchard" - }, - { - "type": "null" - } - ], - "description": "JSON object with Orchard-specific information.\n\nOmitted if `version < 5`." - }, - "overwintered": { - "description": "Whether the `overwintered` flag is set.", - "type": "boolean" - }, - "size": { - "description": "The network-serialized transaction size.", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "time": { - "description": "The transaction time in seconds since epoch (Jan 1 1970 GMT).\n\nThis is always identical to `blocktime`.\n\nOmitted if `blockhash` is either omitted or not in the current best chain.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "txid": { - "description": "The transaction ID (same as provided).", - "type": "string" - }, - "vShieldedOutput": { - "description": "Omitted if `version < 4`.", - "items": { - "$ref": "#/components/schemas/SaplingOutput" - }, - "type": [ - "array", - "null" - ] - }, - "vShieldedSpend": { - "description": "Omitted if `version < 4`.", - "items": { - "$ref": "#/components/schemas/SaplingSpend" - }, - "type": [ - "array", - "null" - ] - }, - "valueBalance": { - "description": "The net value of Sapling Spends minus Outputs in ZEC.\n\nOmitted if `version < 4`.", - "type": [ - "number", - "null" - ] - }, - "valueBalanceZat": { - "description": "The net value of Sapling Spends minus Outputs in zatoshis.\n\nOmitted if `version < 4`.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "version": { - "description": "The transaction version.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "versiongroupid": { - "description": "The version group ID.\n\nOmitted if `overwintered` is `false`.", - "type": [ - "string", - "null" - ] - }, - "vin": { - "description": "The transparent inputs to the transaction.", - "items": { - "$ref": "#/components/schemas/TransparentInput" - }, - "type": "array" - }, - "vout": { - "description": "The transparent outputs from the transaction.", - "items": { - "$ref": "#/components/schemas/TransparentOutput" - }, - "type": "array" - } - }, - "required": [ - "hex", - "txid", - "authdigest", - "size", - "overwintered", - "version", - "locktime", - "vin", - "vout" - ], - "type": "object" - }, - "TransparentAddresses": { - "properties": { - "addresses": { - "items": { - "type": "string" - }, - "type": "array" - }, - "changeAddresses": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "addresses", - "changeAddresses" - ], - "type": "object" - }, - "TransparentInput": { - "properties": { - "coinbase": { - "description": "The coinbase `scriptSig`, encoded as a hex string.\n\nOmitted if this is not a coinbase transaction.", - "type": [ - "string", - "null" - ] - }, - "scriptSig": { - "anyOf": [ - { - "$ref": "#/components/schemas/TransparentScriptSig" - }, - { - "type": "null" - } - ], - "description": "Omitted if this is a coinbase transaction." - }, - "sequence": { - "description": "The script sequence number.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "txid": { - "description": "The transaction ID of the output being spent.\n\nOmitted if this is a coinbase transaction.", - "type": [ - "string", - "null" - ] - }, - "vout": { - "description": "The index of the output being spent within the transaction identified by `txid`.\n\nOmitted if this is a coinbase transaction.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "sequence" - ], - "type": "object" - }, - "TransparentOutput": { - "properties": { - "n": { - "description": "The index of the output within the transaction's `vout` field.", - "format": "uint16", - "maximum": 65535, - "minimum": 0, - "type": "integer" - }, - "scriptPubKey": { - "$ref": "#/components/schemas/TransparentScriptPubKey" - }, - "value": { - "description": "The value in ZEC.", - "minimum": 0, - "type": "number" - }, - "valueSat": { - "description": "The value in zatoshis.", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "valueZat": { - "description": "The value in zatoshis.", - "format": "uint64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "value", - "valueZat", - "valueSat", - "n", - "scriptPubKey" - ], - "type": "object" - }, - "TransparentScriptPubKey": { - "properties": { - "addresses": { - "description": "Array of the transparent P2PKH addresses involved in the script.", - "items": { - "type": "string" - }, - "type": "array" - }, - "asm": { - "description": "The assembly string representation of the script.", - "type": "string" - }, - "hex": { - "description": "The serialized script, encoded as a hex string.", - "type": "string" - }, - "reqSigs": { - "description": "The required number of signatures to spend this output.", - "format": "uint8", - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "type": { - "description": "The type of script.\n\nOne of `[\"pubkey\", \"pubkeyhash\", \"scripthash\", \"multisig\", \"nulldata\", \"nonstandard\"]`.", - "type": "string" - } - }, - "required": [ - "asm", - "hex", - "reqSigs", - "type", - "addresses" - ], - "type": "object" - }, - "TransparentScriptSig": { - "properties": { - "asm": { - "description": "The assembly string representation of the script.", - "type": "string" - }, - "hex": { - "description": "The serialized script, encoded as a hex string.", - "type": "string" - } - }, - "required": [ - "asm", - "hex" - ], - "type": "object" - }, - "UnifiedAddress": { - "properties": { - "address": { - "description": "The unified address corresponding to the diversifier.", - "type": "string" - }, - "diversifier_index": { - "description": "The diversifier index that the UA was derived at.", - "format": "uint128", - "minimum": 0, - "type": "integer" - }, - "receiver_types": { - "description": "The receiver types that the UA contains (valid values are \"p2pkh\", \"sapling\", \"orchard\").", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "diversifier_index", - "receiver_types", - "address" - ], - "type": "object" - }, - "UnifiedAddresses": { - "properties": { - "account": { - "description": "The ZIP 32 account index.", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "addresses": { - "items": { - "$ref": "#/components/schemas/UnifiedAddress" - }, - "type": "array" - }, - "seedfp": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "addresses" - ], - "type": "object" - }, - "UnspentOutput": { - "properties": { - "account_uuid": { - "description": "The UUID of the wallet account that received this output.", - "type": "string" - }, - "address": { - "description": "The Zcash address that received the output.\n\nOmitted if this output was received on an account-internal address (for example, change\nand shielding outputs).", - "type": [ - "string", - "null" - ] - }, - "confirmations": { - "description": "The number of confirmations.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "is_watch_only": { - "description": "`true` if the account that received the output is watch-only", - "type": "boolean" - }, - "memo": { - "description": "Hexadecimal string representation of the memo field.\n\nOmitted if this is a transparent output.", - "type": [ - "string", - "null" - ] - }, - "memoStr": { - "description": "UTF-8 string representation of memo field (if it contains valid UTF-8).", - "type": [ - "string", - "null" - ] - }, - "outindex": { - "description": "The Transparent UTXO, Sapling output or Orchard action index.", - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "pool": { - "description": "The shielded value pool.\n\nOne of `[\"sapling\", \"orchard\", \"transparent\"]`.", - "type": "string" - }, - "txid": { - "description": "The ID of the transaction that created this output.", - "type": "string" - }, - "value": { - "description": "The value of the output in ZEC.", - "minimum": 0, - "type": "number" - }, - "valueZat": { - "description": "The value of the output in zatoshis.", - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "walletInternal": { - "description": "`true` if the output was received by the account's internal viewing key.\n\nThe `address` field is guaranteed be absent when this field is set to `true`, in which case\nit indicates that this may be a change output, an output of a wallet-internal shielding\ntransaction, an output of a wallet-internal cross-account transfer, or otherwise is the\nresult of some wallet-internal operation.", - "type": "boolean" - } - }, - "required": [ - "txid", - "pool", - "outindex", - "confirmations", - "is_watch_only", - "account_uuid", - "walletInternal", - "value", - "valueZat" - ], - "type": "object" - }, - "WalletTx": { - "description": "A transaction that affects an account in a wallet.", - "properties": { - "account_balance_delta": { - "description": "The delta to the account produced by the transaction", - "format": "int64", - "type": "integer" - }, - "account_uuid": { - "description": "The UUID of the account that this transaction entry is acting on.\n\nA transaction that has effects on multiple accounts will have multiple rows in the result.", - "type": "string" - }, - "block_datetime": { - "description": "The human-readable datetime at which the block was mined.", - "type": [ - "string", - "null" - ] - }, - "block_time": { - "description": "The timestamp at which the block was mined.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "expired_unmined": { - "description": "Whether or not the transaction expired without having been mined.", - "type": "boolean" - }, - "expiry_height": { - "description": "The expiry height of the transaction", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "fee_paid": { - "description": "The fee paid by the transaction, if known.", - "format": "uint64", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "mined_height": { - "description": "The height at which the transaction was mined", - "format": "uint32", - "minimum": 0, - "type": [ - "integer", - "null" - ] - }, - "outputs": { - "description": "The outputs of the transaction received by the wallet.", - "items": { - "$ref": "#/components/schemas/WalletTxOutput" - }, - "type": "array" - }, - "received_note_count": { - "description": "The number of outputs received by the transaction.", - "format": "uint", - "minimum": 0, - "type": "integer" - }, - "sent_note_count": { - "description": "The number of outputs produced by the transaction.", - "format": "uint", - "minimum": 0, - "type": "integer" - }, - "txid": { - "description": "The transaction identifier", - "type": "string" - } - }, - "required": [ - "account_uuid", - "txid", - "account_balance_delta", - "sent_note_count", - "received_note_count", - "expired_unmined", - "outputs" - ], - "type": "object" - }, - "WalletTxOutput": { - "description": "Basic information about a transaction output that was either created or received by this\nwallet.", - "properties": { - "from_account": { - "type": [ - "string", - "null" - ] - }, - "is_change": { - "type": "boolean" - }, - "memo": { - "type": [ - "string", - "null" - ] - }, - "output_index": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "pool": { - "type": "string" - }, - "to_account": { - "type": [ - "string", - "null" - ] - }, - "to_address": { - "type": [ - "string", - "null" - ] - }, - "value": { - "format": "uint64", - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "pool", - "output_index", - "value", - "is_change" - ], - "type": "object" - } - } - }, - "info": { - "description": "Z3 RPC request router", - "title": "rpc-router", - "version": "0.1.0" - }, - "methods": [ - { - "description": "Returns all transaction ids in the memory pool, as a JSON array.\n\n# Parameters\n\n- `verbose`: (boolean, optional, default=false) true for a json object, false for array of transaction ids.\n\nzcashd reference: [`getrawmempool`](https://zcash.github.io/rpc/getrawmempool.html)\nmethod: post\ntags: blockchain", - "name": "getrawmempool", - "params": [ - { - "description": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data.", - "name": "verbose", - "schema": { - "type": "boolean" - }, - "summary": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getrawmempool_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns all transaction ids in the memory pool, as a JSON array.", - "x-server": "zebra" - }, - { - "description": "Returns information about a range of Sapling or Orchard subtrees.\n\nzcashd reference: [`z_getsubtreesbyindex`](https://zcash.github.io/rpc/z_getsubtreesbyindex.html) - TODO: fix link\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `pool`: (string, required) The pool from which subtrees should be returned. Either \"sapling\" or \"orchard\".\n- `start_index`: (number, required) The index of the first 2^16-leaf subtree to return.\n- `limit`: (number, optional) The maximum number of subtree values to return.\n\n# Notes\n\nWhile Zebra is doing its initial subtree index rebuild, subtrees will become available\nstarting at the chain tip. This RPC will return an empty list if the `start_index` subtree\nexists, but has not been rebuilt yet. This matches `zcashd`'s behaviour when subtrees aren't\navailable yet. (But `zcashd` does its rebuild before syncing any blocks.)", - "name": "z_getsubtreesbyindex", - "params": [ - { - "description": "The pool from which subtrees should be returned. Either \"sapling\" or \"orchard\".", - "name": "pool", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The pool from which subtrees should be returned. Either \"sapling\" or \"orchard\"." - }, - { - "description": "The index of the first 2^16-leaf subtree to return.", - "name": "start_index", - "required": true, - "schema": { - "$ref": "#/components/schemas/NoteCommitmentSubtreeIndex" - }, - "summary": "The index of the first 2^16-leaf subtree to return." - }, - { - "description": "The maximum number of subtrees to return.", - "name": "limit", - "schema": { - "$ref": "#/components/schemas/NoteCommitmentSubtreeIndex" - }, - "summary": "The maximum number of subtrees to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "z_getsubtreesbyindex_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns information about a range of Sapling or Orchard subtrees.", - "x-server": "zebra" - }, - { - "description": "Returns the hash of the current best blockchain tip block, as a [`GetBlockHash`] JSON string.\n\nzcashd reference: [`getbestblockhash`](https://zcash.github.io/rpc/getbestblockhash.html)\nmethod: post\ntags: blockchain", - "name": "getbestblockhash", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getbestblockhash_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the hash of the current best blockchain tip block, as a [`GetBlockHash`] JSON string.", - "x-server": "zebra" - }, - { - "description": "Stop the running zebrad process.\n\n# Notes\n\n- Works for non windows targets only.\n- Works only if the network of the running zebrad process is `Regtest`.\n\nzcashd reference: [`stop`](https://zcash.github.io/rpc/stop.html)\nmethod: post\ntags: control", - "name": "stop", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "stop_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Stop the running zebrad process.", - "x-server": "zebra" - }, - { - "description": "Returns the transaction ids made by the provided transparent addresses.\n\nzcashd reference: [`getaddresstxids`](https://zcash.github.io/rpc/getaddresstxids.html)\nmethod: post\ntags: address\n\n# Parameters\n\n- `request`: (required) Either:\n - A single address string (e.g., `\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"`), or\n - An object with the following named fields:\n - `addresses`: (array of strings, required) The addresses to get transactions from.\n - `start`: (numeric, optional) The lower height to start looking for transactions (inclusive).\n - `end`: (numeric, optional) The upper height to stop looking for transactions (inclusive).\n\nExample of the object form:\n```json\n{\n \"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"],\n \"start\": 1000,\n \"end\": 2000\n}\n```\n\n# Notes\n\n- Only the multi-argument format is used by lightwalletd and this is what we currently support:\n\n- It is recommended that users call the method with start/end heights such that the response can't be too large.", - "name": "getaddresstxids", - "params": [ - { - "description": "The request object containing the parameters.", - "name": "request", - "required": true, - "schema": { - "$ref": "#/components/schemas/GetAddressTxIdsRequest" - }, - "summary": "The request object containing the parameters." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getaddresstxids_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the transaction ids made by the provided transparent addresses.", - "x-server": "zebra" - }, - { - "description": "Returns the hash of the block of a given height iff the index argument correspond\nto a block in the best chain.\n\nzcashd reference: [`getblockhash`](https://zcash-rpc.github.io/getblockhash.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `index`: (numeric, required, example=1) The block index.\n\n# Notes\n\n- If `index` is positive then index = block height.\n- If `index` is negative then -1 is the last known valid block.", - "name": "getblockhash", - "params": [ - { - "description": "The index of the subtree to return.", - "name": "index", - "required": true, - "schema": { - "format": "int32", - "type": "integer" - }, - "summary": "The index of the subtree to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getblockhash_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the hash of the block of a given height iff the index argument correspond", - "x-server": "zebra" - }, - { - "description": "Sends the raw bytes of a signed transaction to the local node's mempool, if the transaction is valid.\nReturns the [`SentTransactionHash`] for the transaction, as a JSON string.\n\nzcashd reference: [`sendrawtransaction`](https://zcash.github.io/rpc/sendrawtransaction.html)\nmethod: post\ntags: transaction\n\n# Parameters\n\n- `raw_transaction_hex`: (string, required, example=\"signedhex\") The hex-encoded raw transaction bytes.\n- `allow_high_fees`: (bool, optional) A legacy parameter accepted by zcashd but ignored by Zebra.\n\n# Notes\n\nzcashd accepts an optional `allowhighfees` parameter. Zebra doesn't support this parameter,\nbecause lightwalletd doesn't use it.", - "name": "sendrawtransaction", - "params": [ - { - "description": "The hex-encoded raw transaction bytes.", - "name": "raw_transaction_hex", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The hex-encoded raw transaction bytes." - }, - { - "description": "Whether to allow high fees.", - "name": "_allow_high_fees", - "schema": { - "type": "boolean" - }, - "summary": "Whether to allow high fees." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "sendrawtransaction_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Sends the raw bytes of a signed transaction to the local node's mempool, if the transaction is valid.", - "x-server": "zebra" - }, - { - "description": "Returns the estimated network solutions per second based on the last `num_blocks` before\n`height`.\n\nIf `num_blocks` is not supplied, uses 120 blocks. If it is 0 or -1, uses the difficulty\naveraging window.\nIf `height` is not supplied or is -1, uses the tip height.\n\nzcashd reference: [`getnetworksolps`](https://zcash.github.io/rpc/getnetworksolps.html)\nmethod: post\ntags: mining", - "name": "getnetworksolps", - "params": [ - { - "description": "The number of blocks to return.", - "name": "num_blocks", - "schema": { - "format": "int32", - "type": "integer" - }, - "summary": "The number of blocks to return." - }, - { - "description": "The height of the block to return.", - "name": "height", - "schema": { - "format": "int32", - "type": "integer" - }, - "summary": "The height of the block to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getnetworksolps_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the estimated network solutions per second based on the last `num_blocks` before", - "x-server": "zebra" - }, - { - "description": "Returns an OpenRPC schema as a description of this service.", - "name": "rpc.discover", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "rpc.discover_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns an OpenRPC schema as a description of this service.", - "x-server": "zebra" - }, - { - "description": "Returns mining-related information.\n\nzcashd reference: [`getmininginfo`](https://zcash.github.io/rpc/getmininginfo.html)\nmethod: post\ntags: mining", - "name": "getmininginfo", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getmininginfo_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns mining-related information.", - "x-server": "zebra" - }, - { - "description": "Add or remove a node from the address book.\n\n# Parameters\n\n- `addr`: (string, required) The address of the node to add or remove.\n- `command`: (string, required) The command to execute, either \"add\", \"onetry\", or \"remove\".\n\n# Notes\n\nOnly the \"add\" command is currently supported.\n\nzcashd reference: [`addnode`](https://zcash.github.io/rpc/addnode.html)\nmethod: post\ntags: network", - "name": "addnode", - "params": [ - { - "description": "The address to return.", - "name": "addr", - "required": true, - "schema": { - "$ref": "#/components/schemas/PeerSocketAddr" - }, - "summary": "The address to return." - }, - { - "description": "The command to execute.", - "name": "command", - "required": true, - "schema": { - "$ref": "#/components/schemas/AddNodeCommand" - }, - "summary": "The command to execute." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "addnode_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Add or remove a node from the address book.", - "x-server": "zebra" - }, - { - "description": "Submits block to the node to be validated and committed.\nReturns the [`SubmitBlockResponse`] for the operation, as a JSON string.\n\nzcashd reference: [`submitblock`](https://zcash.github.io/rpc/submitblock.html)\nmethod: post\ntags: mining\n\n# Parameters\n\n- `hexdata`: (string, required)\n- `jsonparametersobject`: (string, optional) - currently ignored\n\n# Notes\n\n - `jsonparametersobject` holds a single field, workid, that must be included in submissions if provided by the server.", - "name": "submitblock", - "params": [ - { - "description": "The hex-encoded data to return.", - "name": "hex_data", - "required": true, - "schema": { - "$ref": "#/components/schemas/HexData" - }, - "summary": "The hex-encoded data to return." - }, - { - "description": "The parameters for the command.", - "name": "_parameters", - "schema": { - "$ref": "#/components/schemas/SubmitBlockParameters" - }, - "summary": "The parameters for the command." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "submitblock_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Submits block to the node to be validated and committed.", - "x-server": "zebra" - }, - { - "description": "Reconsiders a previously invalidated block if it exists in the cache of previously invalidated blocks.\n\n# Parameters\n\n- `block_hash`: (hex-encoded block hash, required) The block hash to reconsider.", - "name": "reconsiderblock", - "params": [ - { - "description": "The hash of the block to return.", - "name": "block_hash", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The hash of the block to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "reconsiderblock_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Reconsiders a previously invalidated block if it exists in the cache of previously invalidated blocks.", - "x-server": "zebra" - }, - { - "description": "Checks if a zcash transparent address of type P2PKH, P2SH or TEX is valid.\nReturns information about the given address if valid.\n\nzcashd reference: [`validateaddress`](https://zcash.github.io/rpc/validateaddress.html)\nmethod: post\ntags: util\n\n# Parameters\n\n- `address`: (string, required) The zcash address to validate.", - "name": "validateaddress", - "params": [ - { - "description": "The address to return.", - "name": "address", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The address to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "validateaddress_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Checks if a zcash transparent address of type P2PKH, P2SH or TEX is valid.", - "x-server": "zebra" - }, - { - "description": "Returns the height and hash of the current best blockchain tip block, as a [`GetBlockHeightAndHashResponse`] JSON struct.\n\nzcashd reference: none\nmethod: post\ntags: blockchain", - "name": "getbestblockheightandhash", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getbestblockheightandhash_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the height and hash of the current best blockchain tip block, as a [`GetBlockHeightAndHashResponse`] JSON struct.", - "x-server": "zebra" - }, - { - "description": "Returns the height of the most recent block in the best valid block chain (equivalently,\nthe number of blocks in this chain excluding the genesis block).\n\nzcashd reference: [`getblockcount`](https://zcash.github.io/rpc/getblockcount.html)\nmethod: post\ntags: blockchain", - "name": "getblockcount", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getblockcount_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the height of the most recent block in the best valid block chain (equivalently,", - "x-server": "zebra" - }, - { - "description": "Returns the total balance of a provided `addresses` in an [`AddressBalance`] instance.\n\nzcashd reference: [`getaddressbalance`](https://zcash.github.io/rpc/getaddressbalance.html)\nmethod: post\ntags: address\n\n# Parameters\n\n- `address_strings`: (object, example={\"addresses\": [\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"]}) A JSON map with a single entry\n - `addresses`: (array of strings) A list of base-58 encoded addresses.\n\n# Notes\n\nzcashd also accepts a single string parameter instead of an array of strings, but Zebra\ndoesn't because lightwalletd always calls this RPC with an array of addresses.\n\nzcashd also returns the total amount of Zatoshis received by the addresses, but Zebra\ndoesn't because lightwalletd doesn't use that information.\n\nThe RPC documentation says that the returned object has a string `balance` field, but\nzcashd actually [returns an\ninteger](https://github.com/zcash/lightwalletd/blob/bdaac63f3ee0dbef62bde04f6817a9f90d483b00/common/common.go#L128-L130).", - "name": "getaddressbalance", - "params": [ - { - "description": "The addresses to return.", - "name": "address_strings", - "required": true, - "schema": { - "$ref": "#/components/schemas/GetAddressBalanceRequest" - }, - "summary": "The addresses to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getaddressbalance_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the total balance of a provided `addresses` in an [`AddressBalance`] instance.", - "x-server": "zebra" - }, - { - "description": "Returns software information from the RPC server, as a [`GetInfo`] JSON struct.\n\nzcashd reference: [`getinfo`](https://zcash.github.io/rpc/getinfo.html)\nmethod: post\ntags: control\n\n# Notes\n\n[The zcashd reference](https://zcash.github.io/rpc/getinfo.html) might not show some fields\nin Zebra's [`GetInfo`]. Zebra uses the field names and formats from the\n[zcashd code](https://github.com/zcash/zcash/blob/v4.6.0-1/src/rpc/misc.cpp#L86-L87).\n\nSome fields from the zcashd reference are missing from Zebra's [`GetInfo`]. It only contains the fields\n[required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L91-L95)", - "name": "getinfo", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getinfo_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns software information from the RPC server, as a [`GetInfo`] JSON struct.", - "x-server": "zebra" - }, - { - "description": "Mine blocks immediately. Returns the block hashes of the generated blocks.\n\n# Parameters\n\n- `num_blocks`: (numeric, required, example=1) Number of blocks to be generated.\n\n# Notes\n\nOnly works if the network of the running zebrad process is `Regtest`.\n\nzcashd reference: [`generate`](https://zcash.github.io/rpc/generate.html)\nmethod: post\ntags: generating", - "name": "generate", - "params": [ - { - "description": "The number of blocks to return.", - "name": "num_blocks", - "required": true, - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "The number of blocks to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "generate_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Mine blocks immediately. Returns the block hashes of the generated blocks.", - "x-server": "zebra" - }, - { - "description": "Returns the estimated network solutions per second based on the last `num_blocks` before\n`height`.\n\nThis method name is deprecated, use [`getnetworksolps`](Self::get_network_sol_ps) instead.\nSee that method for details.\n\nzcashd reference: [`getnetworkhashps`](https://zcash.github.io/rpc/getnetworkhashps.html)\nmethod: post\ntags: mining", - "name": "getnetworkhashps", - "params": [ - { - "description": "The number of blocks to return.", - "name": "num_blocks", - "schema": { - "format": "int32", - "type": "integer" - }, - "summary": "The number of blocks to return." - }, - { - "description": "The height of the block to return.", - "name": "height", - "schema": { - "format": "int32", - "type": "integer" - }, - "summary": "The height of the block to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getnetworkhashps_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the estimated network solutions per second based on the last `num_blocks` before", - "x-server": "zebra" - }, - { - "description": "Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct.\n\nzcashd reference: [`getblockchaininfo`](https://zcash.github.io/rpc/getblockchaininfo.html)\nmethod: post\ntags: blockchain\n\n# Notes\n\nSome fields from the zcashd reference are missing from Zebra's [`GetBlockchainInfoResponse`]. It only contains the fields\n[required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89)", - "name": "getblockchaininfo", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getblockchaininfo_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct.", - "x-server": "zebra" - }, - { - "description": "Returns all unspent outputs for a list of addresses.\n\nzcashd reference: [`getaddressutxos`](https://zcash.github.io/rpc/getaddressutxos.html)\nmethod: post\ntags: address\n\n# Parameters\n\n- `request`: (required) Either:\n - A single address string (e.g., `\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\"`), or\n - An object with the following named fields:\n - `addresses`: (array, required, example=[\\\"tmYXBYJj1K7vhejSec5osXK2QsGa5MTisUQ\\\"]) The addresses to get outputs from.\n - `chaininfo`: (boolean, optional, default=false) Include chain info with results\n\n# Notes\n\nlightwalletd always uses the multi-address request, without chaininfo:\n", - "name": "getaddressutxos", - "params": [ - { - "description": "The request object containing the parameters.", - "name": "request", - "required": true, - "schema": { - "$ref": "#/components/schemas/GetAddressUtxosRequest" - }, - "summary": "The request object containing the parameters." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getaddressutxos_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns all unspent outputs for a list of addresses.", - "x-server": "zebra" - }, - { - "description": "Invalidates a block if it is not yet finalized, removing it from the non-finalized\nstate if it is present and rejecting it during contextual validation if it is submitted.\n\n# Parameters\n\n- `block_hash`: (hex-encoded block hash, required) The block hash to invalidate.", - "name": "invalidateblock", - "params": [ - { - "description": "The hash of the block to return.", - "name": "block_hash", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The hash of the block to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "invalidateblock_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Invalidates a block if it is not yet finalized, removing it from the non-finalized", - "x-server": "zebra" - }, - { - "description": "Returns the block subsidy reward of the block at `height`, taking into account the mining slow start.\nReturns an error if `height` is less than the height of the first halving for the current network.\n\nzcashd reference: [`getblocksubsidy`](https://zcash.github.io/rpc/getblocksubsidy.html)\nmethod: post\ntags: mining\n\n# Parameters\n\n- `height`: (numeric, optional, example=1) Can be any valid current or future height.\n\n# Notes\n\nIf `height` is not supplied, uses the tip height.", - "name": "getblocksubsidy", - "params": [ - { - "description": "The height of the block to return.", - "name": "height", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "The height of the block to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getblocksubsidy_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the block subsidy reward of the block at `height`, taking into account the mining slow start.", - "x-server": "zebra" - }, - { - "description": "Returns the raw transaction data, as a [`GetRawTransaction`] JSON string or structure.\n\nzcashd reference: [`getrawtransaction`](https://zcash.github.io/rpc/getrawtransaction.html)\nmethod: post\ntags: transaction\n\n# Parameters\n\n- `txid`: (string, required, example=\"mytxid\") The transaction ID of the transaction to be returned.\n- `verbose`: (number, optional, default=0, example=1) If 0, return a string of hex-encoded data, otherwise return a JSON object.\n- `blockhash` (string, optional) The block in which to look for the transaction", - "name": "getrawtransaction", - "params": [ - { - "description": "The transaction ID to return.", - "name": "txid", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The transaction ID to return." - }, - { - "description": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data.", - "name": "verbose", - "schema": { - "format": "uint8", - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "summary": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data." - }, - { - "description": "The hash of the block to return.", - "name": "block_hash", - "schema": { - "type": "string" - }, - "summary": "The hash of the block to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getrawtransaction_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the raw transaction data, as a [`GetRawTransaction`] JSON string or structure.", - "x-server": "zebra" - }, - { - "description": "Checks if a zcash address of type P2PKH, P2SH, TEX, SAPLING or UNIFIED is valid.\nReturns information about the given address if valid.\n\nzcashd reference: [`z_validateaddress`](https://zcash.github.io/rpc/z_validateaddress.html)\nmethod: post\ntags: util\n\n# Parameters\n\n- `address`: (string, required) The zcash address to validate.\n\n# Notes\n\n- No notes", - "name": "z_validateaddress", - "params": [ - { - "description": "The address to return.", - "name": "address", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The address to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "z_validateaddress_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Checks if a zcash address of type P2PKH, P2SH, TEX, SAPLING or UNIFIED is valid.", - "x-server": "zebra" - }, - { - "description": "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.\n\nzcashd reference: [`getdifficulty`](https://zcash.github.io/rpc/getdifficulty.html)\nmethod: post\ntags: blockchain", - "name": "getdifficulty", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getdifficulty_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.", - "x-server": "zebra" - }, - { - "description": "Returns data about each connected network node.\n\nzcashd reference: [`getpeerinfo`](https://zcash.github.io/rpc/getpeerinfo.html)\nmethod: post\ntags: network", - "name": "getpeerinfo", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getpeerinfo_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns data about each connected network node.", - "x-server": "zebra" - }, - { - "description": "Returns an object containing various state info regarding P2P networking.\n\nzcashd reference: [`getnetworkinfo`](https://zcash.github.io/rpc/getnetworkinfo.html)\nmethod: post\ntags: network", - "name": "getnetworkinfo", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getnetworkinfo_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns an object containing various state info regarding P2P networking.", - "x-server": "zebra" - }, - { - "description": "Returns the list of individual payment addresses given a unified address.\n\nzcashd reference: [`z_listunifiedreceivers`](https://zcash.github.io/rpc/z_listunifiedreceivers.html)\nmethod: post\ntags: wallet\n\n# Parameters\n\n- `address`: (string, required) The zcash unified address to get the list from.\n\n# Notes\n\n- No notes", - "name": "z_listunifiedreceivers", - "params": [ - { - "description": "The address to return.", - "name": "address", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The address to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "z_listunifiedreceivers_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the list of individual payment addresses given a unified address.", - "x-server": "zebra" - }, - { - "description": "Returns information about the given block's Sapling & Orchard tree state.\n\nzcashd reference: [`z_gettreestate`](https://zcash.github.io/rpc/z_gettreestate.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `hash | height`: (string, required, example=\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\") The block hash or height.\n\n# Notes\n\nThe zcashd doc reference above says that the parameter \"`height` can be\nnegative where -1 is the last known valid block\". On the other hand,\n`lightwalletd` only uses positive heights, so Zebra does not support\nnegative heights.", - "name": "z_gettreestate", - "params": [ - { - "description": "The block hash or height to return.", - "name": "hash_or_height", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The block hash or height to return." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "z_gettreestate_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns information about the given block's Sapling & Orchard tree state.", - "x-server": "zebra" - }, - { - "description": "Returns a block template for mining new Zcash blocks.\n\n# Parameters\n\n- `jsonrequestobject`: (string, optional) A JSON object containing arguments.\n\nzcashd reference: [`getblocktemplate`](https://zcash-rpc.github.io/getblocktemplate.html)\nmethod: post\ntags: mining\n\n# Notes\n\nArguments to this RPC are currently ignored.\nLong polling, block proposals, server lists, and work IDs are not supported.\n\nMiners can make arbitrary changes to blocks, as long as:\n- the data sent to `submitblock` is a valid Zcash block, and\n- the parent block is a valid block that Zebra already has, or will receive soon.\n\nZebra verifies blocks in parallel, and keeps recent chains in parallel,\nso moving between chains and forking chains is very cheap.", - "name": "getblocktemplate", - "params": [ - { - "description": "The parameters for the command.", - "name": "parameters", - "schema": { - "$ref": "#/components/schemas/GetBlockTemplateParameters" - }, - "summary": "The parameters for the command." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getblocktemplate_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns a block template for mining new Zcash blocks.", - "x-server": "zebra" - }, - { - "description": "Returns the requested block by hash or height, as a [`GetBlock`] JSON string.\nIf the block is not in Zebra's state, returns\n[error code `-8`.](https://github.com/zcash/zcash/issues/5758) if a height was\npassed or -5 if a hash was passed.\n\nzcashd reference: [`getblock`](https://zcash.github.io/rpc/getblock.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `hash_or_height`: (string, required, example=\"1\") The hash or height for the block to be returned.\n- `verbosity`: (number, optional, default=1, example=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data.\n\n# Notes\n\nThe `size` field is only returned with verbosity=2.\n\nThe undocumented `chainwork` field is not returned.", - "name": "getblock", - "params": [ - { - "description": "The block hash or height to return.", - "name": "hash_or_height", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The block hash or height to return." - }, - { - "description": "Whether to include verbose output.", - "name": "verbosity", - "schema": { - "format": "uint8", - "maximum": 255, - "minimum": 0, - "type": "integer" - }, - "summary": "Whether to include verbose output." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getblock_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the requested block by hash or height, as a [`GetBlock`] JSON string.", - "x-server": "zebra" - }, - { - "description": "Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string.\nIf the block is not in Zebra's state,\nreturns [error code `-8`.](https://github.com/zcash/zcash/issues/5758)\nif a height was passed or -5 if a hash was passed.\n\nzcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html)\nmethod: post\ntags: blockchain\n\n# Parameters\n\n- `hash_or_height`: (string, required, example=\"1\") The hash or height for the block to be returned.\n- `verbose`: (bool, optional, default=false, example=true) false for hex encoded data, true for a json object\n\n# Notes\n\nThe undocumented `chainwork` field is not returned.", - "name": "getblockheader", - "params": [ - { - "description": "The block hash or height to return.", - "name": "hash_or_height", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The block hash or height to return." - }, - { - "description": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data.", - "name": "verbose", - "schema": { - "type": "boolean" - }, - "summary": "Boolean flag to indicate verbosity, true for a json object, false for hex encoded data." - } - ], - "result": { - "description": "An OpenRPC document.", - "name": "getblockheader_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string.", - "x-server": "zebra" - }, - { - "description": "Returns details on the active state of the TX memory pool.\n\nzcash reference: [`getmempoolinfo`](https://zcash.github.io/rpc/getmempoolinfo.html)", - "name": "getmempoolinfo", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "getmempoolinfo_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns details on the active state of the TX memory pool.", - "x-server": "zebra" - }, - { - "description": "Send a transaction with multiple recipients.\n\nThis is an async operation; it returns an operation ID string that you can pass to\n`z_getoperationstatus` or `z_getoperationresult`.\n\nAmounts are decimal numbers with at most 8 digits of precision.\n\nChange generated from one or more transparent addresses flows to a new transparent\naddress, while change generated from a legacy Sapling address returns to itself.\nTODO: https://github.com/zcash/wallet/issues/138\n\nWhen sending from a unified address, change is returned to the internal-only\naddress for the associated unified account.\n\nWhen spending coinbase UTXOs, only shielded recipients are permitted and change is\nnot allowed; the entire value of the coinbase UTXO(s) must be consumed.\nTODO: https://github.com/zcash/wallet/issues/137\n\n# Arguments\n\n- `fromaddress` (string, required) The transparent or shielded address to send the\n funds from. The following special strings are also accepted:\n - `\"ANY_TADDR\"`: Select non-coinbase UTXOs from any transparent addresses\n belonging to the wallet. Use `z_shieldcoinbase` to shield coinbase UTXOs from\n multiple transparent addresses.\n If a unified address is provided for this argument, the TXOs to be spent will be\n selected from those associated with the account corresponding to that unified\n address, from value pools corresponding to the receivers included in the UA.\n- `amounts` (array, required) An array of JSON objects representing the amounts to\n send, with the following fields:\n - `address` (string, required) A taddr, zaddr, or Unified Address.\n - `amount` (numeric, required) The numeric amount in ZEC.\n - `memo` (string, optional) If the address is a zaddr, raw data represented in\n hexadecimal string format. If the output is being sent to a transparent\n address, it’s an error to include this field.\n- `minconf` (numeric, optional) Only use funds confirmed at least this many times.\n- `fee` (numeric, optional) If set, it must be null. Zallet always uses a fee\n calculated according to ZIP 317.\n- `privacy_policy` (string, optional, default=`\"FullPrivacy\"`) Policy for what\n information leakage is acceptable. One of the following strings:\n - `\"FullPrivacy\"`: Only allow fully-shielded transactions (involving a single\n shielded value pool).\n - `\"AllowRevealedAmounts\"`: Allow funds to cross between shielded value pools,\n revealing the amount that crosses pools.\n - `\"AllowRevealedRecipients\"`: Allow transparent recipients. This also implies\n revealing information described under `\"AllowRevealedAmounts\"`.\n - `\"AllowRevealedSenders\"`: Allow transparent funds to be spent, revealing the\n sending addresses and amounts. This implies revealing information described\n under `\"AllowRevealedAmounts\"`.\n - `\"AllowFullyTransparent\"`: Allow transaction to both spend transparent funds\n and have transparent recipients. This implies revealing information described\n under `\"AllowRevealedSenders\"` and `\"AllowRevealedRecipients\"`.\n - `\"AllowLinkingAccountAddresses\"`: Allow selecting transparent coins from the\n full account, rather than just the funds sent to the transparent receiver in\n the provided Unified Address. This implies revealing information described\n under `\"AllowRevealedSenders\"`.\n - `\"NoPrivacy\"`: Allow the transaction to reveal any information necessary to\n create it. This implies revealing information described under\n `\"AllowFullyTransparent\"` and `\"AllowLinkingAccountAddresses\"`.", - "name": "z_sendmany", - "params": [ - { - "description": "The transparent or shielded address to send the funds from.", - "name": "fromaddress", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The transparent or shielded address to send the funds from." - }, - { - "description": "An array of JSON objects representing the amounts to send.", - "name": "amounts", - "required": true, - "schema": { - "items": { - "$ref": "#/components/schemas/AmountParameter" - }, - "type": "array" - }, - "summary": "An array of JSON objects representing the amounts to send." - }, - { - "description": "Only use funds confirmed at least this many times.", - "name": "minconf", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "Only use funds confirmed at least this many times." - }, - { - "description": "If set, it must be null.", - "name": "fee", - "schema": true, - "summary": "If set, it must be null." - }, - { - "description": "Policy for what information leakage is acceptable.", - "name": "privacy_policy", - "schema": { - "type": "string" - }, - "summary": "Policy for what information leakage is acceptable." - } - ], - "result": { - "description": "An async operation ID.", - "name": "z_sendmany_result", - "schema": { - "$ref": "#/components/schemas/OperationId" - }, - "summary": "An async operation ID." - }, - "summary": "Send a transaction with multiple recipients.", - "x-server": "zallet" - }, - { - "description": "For the given account, derives a Unified Address in accordance with the remaining\narguments:\n\n- If no list of receiver types is given (or the empty list `[]`), the best and\n second-best shielded receiver types, along with the \"p2pkh\" (i.e. transparent)\n receiver type, will be used.\n- If no diversifier index is given, then:\n - If a transparent receiver would be included (either because no list of\n receiver types is given, or the provided list includes \"p2pkh\"), the next\n unused index (that is valid for the list of receiver types) will be selected.\n - If only shielded receivers would be included (because a list of receiver types\n is given that does not include \"p2pkh\"), a time-based index will be selected.\n\nThe account parameter must be a UUID or account number that was previously\ngenerated by a call to the `z_getnewaccount` RPC method. The legacy account number\nis only supported for wallets containing a single seed phrase.\n\nOnce a Unified Address has been derived at a specific diversifier index,\nre-deriving it (via a subsequent call to `z_getaddressforaccount` with the same\naccount and index) will produce the same address with the same list of receiver\ntypes. An error will be returned if a different list of receiver types is\nrequested, including when the empty list `[]` is provided (if the default receiver\ntypes don't match).", - "name": "z_getaddressforaccount", - "params": [ - { - "description": "Either the UUID or ZIP 32 account index of the account to derive from.", - "name": "account", - "required": true, - "schema": true, - "summary": "Either the UUID or ZIP 32 account index of the account to derive from." - }, - { - "description": "Receiver types to include in the derived address.", - "name": "receiver_types", - "schema": { - "items": { - "type": "string" - }, - "type": "array" - }, - "summary": "Receiver types to include in the derived address." - }, - { - "description": "A specific diversifier index to derive at.", - "name": "diversifier_index", - "schema": { - "format": "uint128", - "minimum": 0, - "type": "integer" - }, - "summary": "A specific diversifier index to derive at." - } - ], - "result": { - "description": "Information about a derived Unified Address.", - "name": "z_getaddressforaccount_result", - "schema": { - "$ref": "#/components/schemas/Address" - }, - "summary": "Information about a derived Unified Address." - }, - "summary": "For the given account, derives a Unified Address in accordance with the remaining", - "x-server": "zallet" - }, - { - "description": "Returns the total value of funds stored in the node's wallet.\n\nTODO: Currently watchonly addresses cannot be omitted; `include_watchonly` must be\nset to true.\n\n# Arguments\n\n- `minconf` (numeric, optional, default=1) Only include private and transparent\n transactions confirmed at least this many times.\n- `include_watchonly` (bool, optional, default=false) Also include balance in\n watchonly addresses (see 'importaddress' and 'z_importviewingkey').", - "name": "z_gettotalbalance", - "params": [ - { - "description": "Only include notes in transactions confirmed at least this many times.", - "name": "minconf", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "Only include notes in transactions confirmed at least this many times." - }, - { - "description": "Also include balance in watchonly addresses.", - "name": "include_watchonly", - "schema": { - "type": "boolean" - }, - "summary": "Also include balance in watchonly addresses." - } - ], - "result": { - "description": "The total value of funds stored in the wallet.", - "name": "z_gettotalbalance_result", - "schema": { - "$ref": "#/components/schemas/TotalBalance" - }, - "summary": "The total value of funds stored in the wallet." - }, - "summary": "Returns the total value of funds stored in the node's wallet.", - "x-server": "zallet" - }, - { - "description": "Removes the wallet encryption key from memory, locking the wallet.\n\nAfter calling this method, you will need to call `walletpassphrase` again before\nbeing able to call any methods which require the wallet to be unlocked.", - "name": "walletlock", - "params": [], - "result": { - "description": "Empty result indicating success.", - "name": "walletlock_result", - "schema": { - "$ref": "#/components/schemas/ResultType" - }, - "summary": "Empty result indicating success." - }, - "summary": "Removes the wallet encryption key from memory, locking the wallet.", - "x-server": "zallet" - }, - { - "description": "Prepares and returns a new account.\n\nIf the wallet contains more than one UA-compatible HD seed phrase, the `seedfp`\nargument must be provided. Available seed fingerprints can be found in the output\nof the `listaddresses` RPC method.\n\nWithin a UA-compatible HD seed phrase, accounts are numbered starting from zero;\nthis RPC method selects the next available sequential account number.\n\nEach new account is a separate group of funds within the wallet, and adds an\nadditional performance cost to wallet scanning.\n\nUse the `z_getaddressforaccount` RPC method to obtain addresses for an account.", - "name": "z_getnewaccount", - "params": [ - { - "description": "A human-readable name for the account.", - "name": "account_name", - "required": true, - "schema": { - "type": "string" - }, - "summary": "A human-readable name for the account." - }, - { - "description": "ZIP 32 seed fingerprint for the BIP 39 mnemonic phrase from which to derive the account.", - "name": "seedfp", - "schema": { - "type": "string" - }, - "summary": "ZIP 32 seed fingerprint for the BIP 39 mnemonic phrase from which to derive the account." - } - ], - "result": { - "description": "Information about the new account.", - "name": "z_getnewaccount_result", - "schema": { - "$ref": "#/components/schemas/Account" - }, - "summary": "Information about the new account." - }, - "summary": "Prepares and returns a new account.", - "x-server": "zallet" - }, - { - "description": "List all commands, or get help for a specified command.\n\n# Arguments\n- `command` (string, optional) The command to get help on.", - "name": "help", - "params": [ - { - "description": "The command to get help on.", - "name": "command", - "schema": { - "type": "string" - }, - "summary": "The command to get help on." - } - ], - "result": { - "description": "The help response.", - "name": "help_result", - "schema": { - "$ref": "#/components/schemas/ResultType2" - }, - "summary": "The help response." - }, - "summary": "List all commands, or get help for a specified command.", - "x-server": "zallet" - }, - { - "description": "Stop the running zallet process.\n\n# Notes\n\n- Works for non windows targets only.\n- Works only if the network of the running zallet process is `Regtest`.", - "name": "stop", - "params": [], - "result": { - "description": "The stop response.", - "name": "stop_result", - "schema": { - "$ref": "#/components/schemas/ResultType3" - }, - "summary": "The stop response." - }, - "summary": "Stop the running zallet process.", - "x-server": "zallet" - }, - { - "description": "Retrieve the result and status of an operation which has finished, and then remove\nthe operation from memory.\n\n- If the operation has failed, it will include an error object.\n- If the operation has succeeded, it will include the result value.\n- If the operation was cancelled, there will be no error object or result value.\n\n# Arguments\n- `operationid` (array, optional) A list of operation ids we are interested in.\n If not provided, retrieve all finished operations known to the node.", - "name": "z_getoperationresult", - "params": [ - { - "description": "A list of operation ids we are interested in.", - "name": "operationid", - "schema": { - "items": { - "$ref": "#/components/schemas/OperationId" - }, - "type": "array" - }, - "summary": "A list of operation ids we are interested in." - } - ], - "result": { - "description": "The relevant operations.", - "name": "z_getoperationresult_result", - "schema": { - "$ref": "#/components/schemas/ResultType4" - }, - "summary": "The relevant operations." - }, - "summary": "Retrieve the result and status of an operation which has finished, and then remove", - "x-server": "zallet" - }, - { - "description": "Get operation status and any associated result or error data.\n\nThe operation will remain in memory.\n\n- If the operation has failed, it will include an error object.\n- If the operation has succeeded, it will include the result value.\n- If the operation was cancelled, there will be no error object or result value.\n\n# Arguments\n- `operationid` (array, optional) A list of operation ids we are interested in.\n If not provided, examine all operations known to the node.", - "name": "z_getoperationstatus", - "params": [ - { - "description": "A list of operation ids we are interested in.", - "name": "operationid", - "schema": { - "items": { - "$ref": "#/components/schemas/OperationId" - }, - "type": "array" - }, - "summary": "A list of operation ids we are interested in." - } - ], - "result": { - "description": "The relevant operations.", - "name": "z_getoperationstatus_result", - "schema": { - "$ref": "#/components/schemas/ResultType4" - }, - "summary": "The relevant operations." - }, - "summary": "Get operation status and any associated result or error data.", - "x-server": "zallet" - }, - { - "description": "Returns detailed information about in-wallet transaction `txid`.\n\nThis method returns information about spends and outputs within the transaction\nthat are visible to the wallet. Importantly, this does not include information\nabout spent notes that are not controlled by spending or viewing keys in the\nwallet, and so callers MUST NOT use the `spends` or `outputs` fields to compute\nbalances or fees themselves. Use the provided `accounts` and `fee` fields instead.", - "name": "z_viewtransaction", - "params": [ - { - "description": "The ID of the transaction to view.", - "name": "txid", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The ID of the transaction to view." - } - ], - "result": { - "description": "Detailed information about an in-wallet transaction.", - "name": "z_viewtransaction_result", - "schema": { - "$ref": "#/components/schemas/Transaction" - }, - "summary": "Detailed information about an in-wallet transaction." - }, - "summary": "Returns detailed information about in-wallet transaction `txid`.", - "x-server": "zallet" - }, - { - "description": "Stores the wallet decryption key in memory for `timeout` seconds.\n\nIf the wallet is locked, this API must be invoked prior to performing operations\nthat require the availability of private keys, such as sending funds.\n\nIssuing the `walletpassphrase` command while the wallet is already unlocked will\nset a new unlock time that overrides the old one.", - "name": "walletpassphrase", - "params": [ - { - "description": "The passphrase for decrypting the wallet's age identity.", - "name": "passphrase", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The passphrase for decrypting the wallet's age identity." - }, - { - "description": "Time in seconds after which the wallet will relock.", - "name": "timeout", - "required": true, - "schema": { - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "summary": "Time in seconds after which the wallet will relock." - } - ], - "result": { - "description": "Empty result indicating success.", - "name": "walletpassphrase_result", - "schema": { - "$ref": "#/components/schemas/ResultType5" - }, - "summary": "Empty result indicating success." - }, - "summary": "Stores the wallet decryption key in memory for `timeout` seconds.", - "x-server": "zallet" - }, - { - "description": "Returns a list of the wallet's transactions, optionally filtered by account and block\nrange.\n\n# Arguments\n- `account_uuid`: The UUID of the wallet account. If omitted, return transactions for all\n accounts in the wallet.\n- `start_height`: The inclusive lower bound of block heights for which transactions mined\n in those blocks should be returned. If omitted, the start height will default to the\n account birthday height if an account UUID is specified, or the minimum birthday\n height among accounts in the wallet if no account is specified.\n- `end_height`: The exclusive upper bound of block heights for which transactions mined\n in those blocks should be returned. If omitted, return all transactions mined or created\n above the start height.\n- `offset`: An optional number of transactions to skip over before a page of results is\n returned. Defaults to zero.\n- `limit`: An optional upper bound on the number of results that should be returned in a\n page. \n\nWARNING: This is currently an experimental feature; arguments and result data may change at\nany time.", - "name": "z_listtransactions", - "params": [ - { - "description": "The UUID of the account to list transactions for.", - "name": "account_uuid", - "schema": { - "type": "string" - }, - "summary": "The UUID of the account to list transactions for." - }, - { - "description": "The (inclusive) lower bound on block heights for which transactions should be retrieved", - "name": "start_height", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "The (inclusive) lower bound on block heights for which transactions should be retrieved" - }, - { - "description": "The (exclusive) upper bound on block heights for which transactions should be retrieved", - "name": "end_height", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "The (exclusive) upper bound on block heights for which transactions should be retrieved" - }, - { - "description": "The number of results to skip before returning a page of results.", - "name": "offset", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "The number of results to skip before returning a page of results." - }, - { - "description": "The maximum number of results to return from a single call.", - "name": "limit", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "The maximum number of results to return from a single call." - } - ], - "result": { - "description": "A list of transactions involving the wallet.", - "name": "z_listtransactions_result", - "schema": { - "$ref": "#/components/schemas/ResultType6" - }, - "summary": "A list of transactions involving the wallet." - }, - "summary": "Returns a list of the wallet's transactions, optionally filtered by account and block", - "x-server": "zallet" - }, - { - "description": "", - "name": "z_listaccounts", - "params": [], - "result": { - "description": "A list of accounts.", - "name": "z_listaccounts_result", - "schema": { - "$ref": "#/components/schemas/ResultType7" - }, - "summary": "A list of accounts." - }, - "summary": "", - "x-server": "zallet" - }, - { - "description": "Returns wallet state information.", - "name": "getwalletinfo", - "params": [], - "result": { - "description": "The wallet state information.", - "name": "getwalletinfo_result", - "schema": { - "$ref": "#/components/schemas/GetWalletInfo" - }, - "summary": "The wallet state information." - }, - "summary": "Returns wallet state information.", - "x-server": "zallet" - }, - { - "description": "Returns the number of notes available in the wallet for each shielded value pool.\n\n# Arguments\n- `minconf`: Only include notes in transactions confirmed at least this many times\n (default = 1). Must be at least 1 when `as_of_height` is provided.\n- `as_of_height`: Execute the query as if it were run when the blockchain was at the height\n specified by this argument. The default is to use the entire blockchain that the node is\n aware of. -1 can be used as in other RPC calls to indicate the current height (including\n the mempool), but this does not support negative values in general. A “future” height will\n fall back to the current height.", - "name": "z_getnotescount", - "params": [ - { - "description": "Only include notes in transactions confirmed at least this many times.", - "name": "minconf", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "Only include notes in transactions confirmed at least this many times." - }, - { - "description": "Execute the query as if it were run when the blockchain was at the height specified by this argument.", - "name": "as_of_height", - "schema": { - "format": "int64", - "type": "integer" - }, - "summary": "Execute the query as if it were run when the blockchain was at the height specified by this argument." - } - ], - "result": { - "description": "The number of notes in the wallet.", - "name": "z_getnotescount_result", - "schema": { - "$ref": "#/components/schemas/GetNotesCount" - }, - "summary": "The number of notes in the wallet." - }, - "summary": "Returns the number of notes available in the wallet for each shielded value pool.", - "x-server": "zallet" - }, - { - "description": "Returns a record of the individual receivers contained within the provided UA,\nkeyed by receiver type. The UA may not have receivers for some receiver types,\nin which case those keys will be absent.\n\nTransactions that send funds to any of the receivers returned by this RPC\nmethod will be detected by the wallet as having been sent to the unified\naddress.\n\n# Arguments\n- `unified_address` (string, required) The unified address to inspect.", - "name": "z_listunifiedreceivers", - "params": [ - { - "description": "The unified address to inspect.", - "name": "unified_address", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The unified address to inspect." - } - ], - "result": { - "description": "The receivers within a unified address.", - "name": "z_listunifiedreceivers_result", - "schema": { - "$ref": "#/components/schemas/ListUnifiedReceivers" - }, - "summary": "The receivers within a unified address." - }, - "summary": "Returns a record of the individual receivers contained within the provided UA,", - "x-server": "zallet" - }, - { - "description": "Returns the list of operation ids currently known to the wallet.\n\n# Arguments\n- `status` (string, optional) Filter result by the operation's state e.g. \"success\".", - "name": "z_listoperationids", - "params": [ - { - "description": "Filter result by the operation's state e.g. \"success\".", - "name": "status", - "schema": { - "type": "string" - }, - "summary": "Filter result by the operation's state e.g. \"success\"." - } - ], - "result": { - "description": "A list of operation IDs.", - "name": "z_listoperationids_result", - "schema": { - "$ref": "#/components/schemas/ResultType8" - }, - "summary": "A list of operation IDs." - }, - "summary": "Returns the list of operation ids currently known to the wallet.", - "x-server": "zallet" - }, - { - "description": "Returns an array of unspent shielded notes with between minconf and maxconf\n(inclusive) confirmations.\n\nResults may be optionally filtered to only include notes sent to specified\naddresses. When `minconf` is 0, unspent notes with zero confirmations are\nreturned, even though they are not immediately spendable.\n\n# Arguments\n- `minconf`: Select outputs with at least this many confirmations (default = 1). Must be at\n least 1 when `as_of_height` is provided.\n- `maxconf`: Select outputs with at most this many confirmations (default = unlimited).\n- `include_watchonly`: Include notes/utxos for which the wallet does not provide spending\n capability (default = false).\n- `addresses`: A list of addresses for which to retrieve UTXOs. For shielded addresses that\n correspond to a unified account, unspent notes belonging to that account are returned\n irrespective of whether the provided address's diversifier corresponds to the diversifier\n of the address that received the funds. If this parameter is omitted or empty, all notes\n are returned, irrespective of account. (default = None)\n- `as_of_height`: Execute the query as if it were run when the blockchain was at the height\n specified by this argument. The default is to use the entire blockchain that the node is\n aware of. -1 can be used as in other RPC calls to indicate the current height (including\n the mempool), but this does not support negative values in general. A “future” height will\n fall back to the current height.", - "name": "z_listunspent", - "params": [ - { - "description": "Only include outputs of transactions confirmed at least this many times.", - "name": "minconf", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "Only include outputs of transactions confirmed at least this many times." - }, - { - "description": "Only include outputs of transactions confirmed at most this many times.", - "name": "maxconf", - "schema": { - "format": "uint32", - "minimum": 0, - "type": "integer" - }, - "summary": "Only include outputs of transactions confirmed at most this many times." - }, - { - "description": "Also include outputs received at watch-only addresses.", - "name": "include_watchonly", - "schema": { - "type": "boolean" - }, - "summary": "Also include outputs received at watch-only addresses." - }, - { - "description": "If non-empty, only outputs received by the provided addresses will be returned.", - "name": "addresses", - "schema": { - "items": { - "type": "string" - }, - "type": "array" - }, - "summary": "If non-empty, only outputs received by the provided addresses will be returned." - }, - { - "description": "Execute the query as if it were run when the blockchain was at the height specified by this argument.", - "name": "as_of_height", - "schema": { - "format": "int64", - "type": "integer" - }, - "summary": "Execute the query as if it were run when the blockchain was at the height specified by this argument." - } - ], - "result": { - "description": "A list of unspent notes.", - "name": "z_listunspent_result", - "schema": { - "$ref": "#/components/schemas/ResultType9" - }, - "summary": "A list of unspent notes." - }, - "summary": "Returns an array of unspent shielded notes with between minconf and maxconf", - "x-server": "zallet" - }, - { - "description": "Tells the wallet to track specific accounts.\n\nReturns the UUIDs within this Zallet instance of the newly-tracked accounts.\nAccounts that are already tracked by the wallet are ignored.\n\nAfter calling this method, a subsequent call to `z_getnewaccount` will add the\nfirst account with index greater than all indices provided here for the\ncorresponding `seedfp` (as well as any already tracked by the wallet).\n\nEach tracked account is a separate group of funds within the wallet, and adds an\nadditional performance cost to wallet scanning.\n\nUse the `z_getaddressforaccount` RPC method to obtain addresses for an account.\n\n# Arguments\n\n- `accounts` (array, required) An array of JSON objects representing the accounts\n to recover, with the following fields:\n - `name` (string, required)\n - `seedfp` (string, required) The seed fingerprint for the mnemonic phrase from\n which the account is derived. Available seed fingerprints can be found in the\n output of the `listaddresses` RPC method.\n - `zip32_account_index` (numeric, required)\n - `birthday_height` (numeric, required)", - "name": "z_recoveraccounts", - "params": [ - { - "description": "An array of JSON objects representing the accounts to recover.", - "name": "accounts", - "required": true, - "schema": { - "items": { - "$ref": "#/components/schemas/AccountParameter" - }, - "type": "array" - }, - "summary": "An array of JSON objects representing the accounts to recover." - } - ], - "result": { - "description": "The list of recovered accounts.", - "name": "z_recoveraccounts_result", - "schema": { - "$ref": "#/components/schemas/Accounts" - }, - "summary": "The list of recovered accounts." - }, - "summary": "Tells the wallet to track specific accounts.", - "x-server": "zallet" - }, - { - "description": "Returns the raw transaction data for the given transaction ID.\n\nNOTE: If `blockhash` is provided, only that block will be searched, and if the\ntransaction is in the mempool or other blocks, or if the node backing this wallet\ndoes not have the given block available, the transaction will not be found.\n\n# Arguments\n- `txid` (string, required) The transaction ID.\n- `verbose` (numeric, optional, default=0) If 0, return a string of hex-encoded\n data. If non-zero, return a JSON object with information about `txid`.\n- `blockhash` (string, optional) The block in which to look for the transaction.", - "name": "getrawtransaction", - "params": [ - { - "description": "The ID of the transaction to fetch.", - "name": "txid", - "required": true, - "schema": { - "type": "string" - }, - "summary": "The ID of the transaction to fetch." - }, - { - "description": "If 0, return a string of hex-encoded data. If non-zero, return a JSON object with information about `txid`", - "name": "verbose", - "schema": { - "format": "uint64", - "minimum": 0, - "type": "integer" - }, - "summary": "If 0, return a string of hex-encoded data. If non-zero, return a JSON object with information about `txid`" - }, - { - "description": "The block in which to look for the transaction.", - "name": "blockhash", - "schema": { - "type": "string" - }, - "summary": "The block in which to look for the transaction." - } - ], - "result": { - "description": "The `getrawtransaction` response.", - "name": "getrawtransaction_result", - "schema": { - "$ref": "#/components/schemas/ResultType10" - }, - "summary": "The `getrawtransaction` response." - }, - "summary": "Returns the raw transaction data for the given transaction ID.", - "x-server": "zallet" - }, - { - "description": "Returns an OpenRPC schema as a description of this service.", - "name": "rpc.discover", - "params": [], - "result": { - "description": "An OpenRPC document.", - "name": "rpc.discover_result", - "schema": { - "$ref": "#/components/schemas/OpenRPC%20Schema" - }, - "summary": "An OpenRPC document." - }, - "summary": "Returns an OpenRPC schema as a description of this service.", - "x-server": "zallet" - }, - { - "description": "Lists the addresses managed by this wallet by source.\n\nSources include:\n- Addresses generated from randomness by a legacy `zcashd` wallet.\n- Sapling addresses generated from the legacy `zcashd` HD seed.\n- Imported watchonly transparent addresses.\n- Shielded addresses tracked using imported viewing keys.\n- Addresses derived from mnemonic seed phrases.\n\nIn the case that a source does not have addresses for a value pool, the key\nassociated with that pool will be absent.\n\nREMINDER: It is recommended that you back up your wallet files regularly. If you\nhave not imported externally-produced keys, it only necessary to have backed up\nthe wallet's key storage file.", - "name": "listaddresses", - "params": [], - "result": { - "description": "A list of address sources.", - "name": "listaddresses_result", - "schema": { - "$ref": "#/components/schemas/ResultType11" - }, - "summary": "A list of address sources." - }, - "summary": "Lists the addresses managed by this wallet by source.", - "x-server": "zallet" - } - ], - "openrpc": "1.3.2", - "servers": [ - { - "name": "router", - "url": "http://localhost:8080/" - } - ] -} \ No newline at end of file From a19a8454b6e858e0fa8ca2a4932b36c7e8e2ce6d Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 6 Mar 2026 09:13:18 -0300 Subject: [PATCH 27/27] consistency --- rpc-router/README.md | 4 +++- rpc-router/src/defaults.rs | 22 +++++++++++++++++++ rpc-router/src/integration_tests.rs | 6 +++--- rpc-router/src/main.rs | 33 +++++++++++++++-------------- 4 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 rpc-router/src/defaults.rs diff --git a/rpc-router/README.md b/rpc-router/README.md index 76e516e..00c8f4a 100644 --- a/rpc-router/README.md +++ b/rpc-router/README.md @@ -33,6 +33,8 @@ Wait until both services are healthy, then note the RPC ports from your `.env` f > **Note:** A `openrpc.py` QA helper that spawned Zebra and Zallet in regtest mode previously existed in the Zebra repository but was removed. It has not been ported to the [zcash/integration-tests](https://github.com/zcash/integration-tests) repository. +> **Note:** For experimental Z3 regtest mode of the router see [Regtest Environment](regtest/README.md). + ### Running the RPC Router ```bash @@ -90,7 +92,7 @@ INFO rpc_router: Routing getwalletinfo to Zallet You can interact with the merged OpenRPC schema using the OpenRPC Playground, pointed at your running router: -[Playground](https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=http://127.0.0.1:8181&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false) +[Playground](https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=http://127.0.0.1:8080&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false) When using the inspector, make sure the target server URL is set to: diff --git a/rpc-router/src/defaults.rs b/rpc-router/src/defaults.rs new file mode 100644 index 0000000..ec7ff16 --- /dev/null +++ b/rpc-router/src/defaults.rs @@ -0,0 +1,22 @@ +//! Default constants +use std::net::SocketAddr; + +pub(crate) const ZEBRA_URL: &str = "http://127.0.0.1:20251"; + +pub(crate) const ZALLET_URL: &str = "http://127.0.0.1:25251"; + +pub(crate) const ZAINO_URL: &str = "http://zaino:8237"; + +pub(crate) const RPC_USER: &str = "zebra"; + +pub(crate) const RPC_PASSWORD: &str = "zebra"; + +pub(crate) const CORS_ORIGIN: &str = "https://playground.open-rpc.org"; + +pub(crate) const LISTEN_PORT: u16 = 8080; + +pub(crate) const PLAYGROUND_URL: &str = "https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl={{addr}}&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"; + +pub(crate) fn playground_url(addr: SocketAddr) -> String { + PLAYGROUND_URL.replace("{{addr}}", &addr.to_string()) +} \ No newline at end of file diff --git a/rpc-router/src/integration_tests.rs b/rpc-router/src/integration_tests.rs index dd99141..29ada87 100644 --- a/rpc-router/src/integration_tests.rs +++ b/rpc-router/src/integration_tests.rs @@ -107,7 +107,7 @@ async fn start_router(zebra_url: &str, zallet_url: &str, zaino_url: &str) -> Rou let config = Arc::new(Config { zebra_url: zebra_url.to_string(), zallet_url: zallet_url.to_string(), - zaino_url: zaino_url.to_string(), + _zaino_url: zaino_url.to_string(), listen_port: 0, rpc_user: "zebra".to_string(), rpc_password: "zebra".to_string(), @@ -264,7 +264,7 @@ async fn test_zallet_method_routing() { } #[tokio::test] -async fn test_unknown_method_falls_back_to_zaino() { +async fn test_unknown_method_falls_back_to_zebra() { let zebra = start_zebra_mock().await; let zallet = start_zallet_mock().await; let zaino = start_zaino_mock().await; @@ -281,5 +281,5 @@ async fn test_unknown_method_falls_back_to_zaino() { assert_eq!(resp.status(), 200); let body: Value = resp.json().await.unwrap(); - assert_eq!(body["result"], "zaino-response"); + assert_eq!(body["result"], "zebra-response"); } diff --git a/rpc-router/src/main.rs b/rpc-router/src/main.rs index 775520a..6ab3e76 100644 --- a/rpc-router/src/main.rs +++ b/rpc-router/src/main.rs @@ -5,7 +5,6 @@ //! to determine which methods belong to which service. use std::{env, net::SocketAddr, sync::Arc}; -const PLAYGROUND_URL: &str = "https://playground.open-rpc.org/?uiSchema[appBar][ui:title]=Zcash&uiSchema[appBar][ui:logoUrl]=https://z.cash/wp-content/uploads/2023/03/zcash-logo.gif&schemaUrl=http://127.0.0.1:8181&uiSchema[appBar][ui:splitView]=false&uiSchema[appBar][ui:edit]=false&uiSchema[appBar][ui:input]=false&uiSchema[appBar][ui:examplesDropdown]=false&uiSchema[appBar][ui:transports]=false"; use anyhow::Result; use base64::{engine::general_purpose, Engine as _}; @@ -27,6 +26,14 @@ use serde_json::{json, Value}; use tokio::net::TcpListener; use tracing::{error, info, warn}; +mod defaults; + +#[cfg(test)] +mod unit_tests; + +#[cfg(test)] +mod integration_tests; + /// Structure to parse incoming JSON-RPC requests. #[derive(Deserialize, Debug)] struct RpcRequest { @@ -38,7 +45,7 @@ struct RpcRequest { struct Config { zebra_url: String, zallet_url: String, - zaino_url: String, + _zaino_url: String, rpc_user: String, rpc_password: String, cors_origin: String, @@ -49,18 +56,18 @@ impl Config { fn from_env() -> Self { Self { zebra_url: env::var("ZEBRA_URL") - .unwrap_or_else(|_| "http://127.0.0.1:20251".to_string()), + .unwrap_or_else(|_| defaults::ZEBRA_URL.to_string()), zallet_url: env::var("ZALLET_URL") - .unwrap_or_else(|_| "http://127.0.0.1:25251".to_string()), - zaino_url: env::var("ZAINO_URL").unwrap_or_else(|_| "http://zaino:8237".to_string()), - rpc_user: env::var("RPC_USER").unwrap_or_else(|_| "zebra".to_string()), - rpc_password: env::var("RPC_PASSWORD").unwrap_or_else(|_| "zebra".to_string()), + .unwrap_or_else(|_| defaults::ZALLET_URL.to_string()), + _zaino_url: env::var("ZAINO_URL").unwrap_or_else(|_| defaults::ZAINO_URL.to_string()), + rpc_user: env::var("RPC_USER").unwrap_or_else(|_| defaults::RPC_USER.to_string()), + rpc_password: env::var("RPC_PASSWORD").unwrap_or_else(|_| defaults::RPC_PASSWORD.to_string()), cors_origin: env::var("CORS_ORIGIN") - .unwrap_or_else(|_| "https://playground.open-rpc.org".to_string()), + .unwrap_or_else(|_| defaults::CORS_ORIGIN.to_string()), listen_port: env::var("LISTEN_PORT") .ok() .and_then(|p| p.parse().ok()) - .unwrap_or(8080), + .unwrap_or(defaults::LISTEN_PORT), } } } @@ -355,7 +362,7 @@ async fn main() -> Result<()> { let listener = TcpListener::bind(addr).await?; info!("RPC Router listening on {}", addr); info!("You can use the following playground URL:"); - info!("{}", PLAYGROUND_URL); + info!("{}", defaults::playground_url(addr)); run(config, listener, z3).await } @@ -381,9 +388,3 @@ async fn run(config: Arc, listener: TcpListener, z3: Z3Schema) -> Result }); } } - -#[cfg(test)] -mod unit_tests; - -#[cfg(test)] -mod integration_tests;