diff --git a/Cargo.lock b/Cargo.lock
index 619f6ae..140daec 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -49,9 +49,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.19"
+version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
+checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -79,29 +79,29 @@ dependencies = [
[[package]]
name = "anstyle-query"
-version = "1.1.3"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
+checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.9"
+version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
+checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "anyhow"
-version = "1.0.98"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "arrayvec"
@@ -133,9 +133,9 @@ dependencies = [
[[package]]
name = "async-trait"
-version = "0.1.88"
+version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
@@ -332,9 +332,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
[[package]]
name = "block-buffer"
@@ -380,9 +380,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.31"
+version = "1.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2"
+checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
dependencies = [
"shlex",
]
@@ -395,9 +395,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
-version = "1.0.1"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cfg_aliases"
@@ -422,9 +422,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.42"
+version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882"
+checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
dependencies = [
"clap_builder",
"clap_derive",
@@ -432,9 +432,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.42"
+version = "4.5.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966"
+checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
dependencies = [
"anstream",
"anstyle",
@@ -444,9 +444,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.41"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck",
"proc-macro2",
@@ -563,7 +563,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"crossterm_winapi",
"futures-core",
"mio 1.0.4",
@@ -621,7 +621,7 @@ dependencies = [
"ed25519-bip32",
"futures",
"hex",
- "indexmap 2.10.0",
+ "indexmap 2.11.0",
"inquire",
"jsonrpsee",
"num-format",
@@ -790,9 +790,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
@@ -947,7 +947,7 @@ dependencies = [
"js-sys",
"libc",
"r-efi",
- "wasi 0.14.2+wasi-0.2.4",
+ "wasi 0.14.3+wasi-0.2.4",
"wasm-bindgen",
]
@@ -1005,9 +1005,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.11"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
+checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
dependencies = [
"atomic-waker",
"bytes",
@@ -1015,7 +1015,7 @@ dependencies = [
"futures-core",
"futures-sink",
"http",
- "indexmap 2.10.0",
+ "indexmap 2.11.0",
"slab",
"tokio",
"tokio-util",
@@ -1040,9 +1040,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
-version = "0.15.4"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
@@ -1118,13 +1118,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
+checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
dependencies = [
+ "atomic-waker",
"bytes",
"futures-channel",
- "futures-util",
+ "futures-core",
"h2",
"http",
"http-body",
@@ -1132,6 +1133,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
+ "pin-utils",
"smallvec",
"tokio",
"want",
@@ -1310,9 +1312,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
-version = "1.0.3"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
dependencies = [
"idna_adapter",
"smallvec",
@@ -1342,12 +1344,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.10.0"
+version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
+checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
dependencies = [
"equivalent",
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
"serde",
]
@@ -1363,7 +1365,7 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"crossterm 0.25.0",
"dyn-clone",
"fuzzy-matcher",
@@ -1398,11 +1400,11 @@ dependencies = [
[[package]]
name = "io-uring"
-version = "0.7.9"
+version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
+checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"cfg-if",
"libc",
]
@@ -1493,9 +1495,9 @@ dependencies = [
[[package]]
name = "jsonrpsee"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16"
+checksum = "3f3f48dc3e6b8bd21e15436c1ddd0bc22a6a54e8ec46fedd6adf3425f396ec6a"
dependencies = [
"jsonrpsee-client-transport",
"jsonrpsee-core",
@@ -1507,9 +1509,9 @@ dependencies = [
[[package]]
name = "jsonrpsee-client-transport"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2a320a3f1464e4094f780c4d48413acd786ce5627aaaecfac9e9c7431d13ae1"
+checksum = "cf36eb27f8e13fa93dcb50ccb44c417e25b818cfa1a481b5470cd07b19c60b98"
dependencies = [
"base64 0.22.1",
"futures-channel",
@@ -1522,7 +1524,7 @@ dependencies = [
"rustls-pki-types",
"rustls-platform-verifier",
"soketto",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"tokio",
"tokio-rustls",
"tokio-util",
@@ -1532,9 +1534,9 @@ dependencies = [
[[package]]
name = "jsonrpsee-core"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547"
+checksum = "316c96719901f05d1137f19ba598b5fe9c9bc39f4335f67f6be8613921946480"
dependencies = [
"async-trait",
"bytes",
@@ -1548,7 +1550,7 @@ dependencies = [
"rustc-hash",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"tokio",
"tokio-stream",
"tower 0.5.2",
@@ -1558,9 +1560,9 @@ dependencies = [
[[package]]
name = "jsonrpsee-http-client"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6962d2bd295f75e97dd328891e58fce166894b974c1f7ce2e7597f02eeceb791"
+checksum = "790bedefcec85321e007ff3af84b4e417540d5c87b3c9779b9e247d1bcc3dab8"
dependencies = [
"base64 0.22.1",
"http-body",
@@ -1573,7 +1575,7 @@ dependencies = [
"rustls-platform-verifier",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"tokio",
"tower 0.5.2",
"url",
@@ -1581,21 +1583,21 @@ dependencies = [
[[package]]
name = "jsonrpsee-types"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca"
+checksum = "bc88ff4688e43cc3fa9883a8a95c6fa27aa2e76c96e610b737b6554d650d7fd5"
dependencies = [
"http",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
]
[[package]]
name = "jsonrpsee-wasm-client"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b67695cbcf4653f39f8f8738925547e0e23fd9fe315bccf951097b9f6a38781"
+checksum = "7902885de4779f711a95d82c8da2d7e5f9f3a7c7cfa44d51c067fd1c29d72a3c"
dependencies = [
"jsonrpsee-client-transport",
"jsonrpsee-core",
@@ -1605,9 +1607,9 @@ dependencies = [
[[package]]
name = "jsonrpsee-ws-client"
-version = "0.25.1"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2da2694c9ff271a9d3ebfe520f6b36820e85133a51be77a3cb549fd615095261"
+checksum = "9b6fceceeb05301cc4c065ab3bd2fa990d41ff4eb44e4ca1b30fa99c057c3e79"
dependencies = [
"http",
"jsonrpsee-client-transport",
@@ -1625,9 +1627,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
-version = "0.2.174"
+version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "linux-raw-sys"
@@ -1669,7 +1671,7 @@ version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
]
[[package]]
@@ -2164,9 +2166,9 @@ dependencies = [
[[package]]
name = "percent-encoding"
-version = "2.3.1"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pest"
@@ -2178,7 +2180,7 @@ dependencies = [
"miette",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"ucd-trie",
]
@@ -2222,7 +2224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
dependencies = [
"fixedbitset",
- "indexmap 2.10.0",
+ "indexmap 2.11.0",
]
[[package]]
@@ -2283,9 +2285,9 @@ dependencies = [
[[package]]
name = "prettyplease"
-version = "0.2.36"
+version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
@@ -2293,9 +2295,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
@@ -2354,9 +2356,9 @@ dependencies = [
[[package]]
name = "quinn"
-version = "0.11.8"
+version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
+checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
dependencies = [
"bytes",
"cfg_aliases",
@@ -2365,8 +2367,8 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
- "socket2 0.5.10",
- "thiserror 2.0.12",
+ "socket2 0.6.0",
+ "thiserror 2.0.16",
"tokio",
"tracing",
"web-time",
@@ -2374,9 +2376,9 @@ dependencies = [
[[package]]
name = "quinn-proto"
-version = "0.11.12"
+version = "0.11.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
+checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31"
dependencies = [
"bytes",
"getrandom 0.3.3",
@@ -2387,7 +2389,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"tinyvec",
"tracing",
"web-time",
@@ -2395,16 +2397,16 @@ dependencies = [
[[package]]
name = "quinn-udp"
-version = "0.5.13"
+version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970"
+checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2 0.5.10",
+ "socket2 0.6.0",
"tracing",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -2487,7 +2489,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"cassowary",
"compact_str",
"crossterm 0.28.1",
@@ -2508,7 +2510,7 @@ version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
]
[[package]]
@@ -2533,9 +2535,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.11.1"
+version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
dependencies = [
"aho-corasick",
"memchr",
@@ -2545,9 +2547,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.9"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
dependencies = [
"aho-corasick",
"memchr",
@@ -2556,15 +2558,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "reqwest"
-version = "0.12.22"
+version = "0.12.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
+checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
dependencies = [
"base64 0.22.1",
"bytes",
@@ -2630,7 +2632,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -2643,7 +2645,7 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"errno",
"libc",
"linux-raw-sys 0.9.4",
@@ -2736,9 +2738,9 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.21"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
@@ -2796,11 +2798,11 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
-version = "3.2.0"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
+checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"core-foundation",
"core-foundation-sys",
"libc",
@@ -2845,9 +2847,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.142"
+version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
+checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
dependencies = [
"itoa",
"memchr",
@@ -2886,7 +2888,7 @@ dependencies = [
"chrono",
"hex",
"indexmap 1.9.3",
- "indexmap 2.10.0",
+ "indexmap 2.11.0",
"schemars 0.9.0",
"schemars 1.0.4",
"serde",
@@ -2978,9 +2980,9 @@ dependencies = [
[[package]]
name = "slab"
-version = "0.4.10"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
+checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
[[package]]
name = "slug"
@@ -3123,9 +3125,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
[[package]]
name = "syn"
-version = "2.0.104"
+version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -3160,25 +3162,25 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
-version = "3.20.0"
+version = "3.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
+checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
dependencies = [
"fastrand",
"getrandom 0.3.3",
"once_cell",
"rustix 1.0.8",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "terminal_size"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
+checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
dependencies = [
"rustix 1.0.8",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -3202,11 +3204,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.12"
+version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
dependencies = [
- "thiserror-impl 2.0.12",
+ "thiserror-impl 2.0.16",
]
[[package]]
@@ -3222,9 +3224,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
-version = "2.0.12"
+version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
dependencies = [
"proc-macro2",
"quote",
@@ -3283,9 +3285,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
+checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [
"tinyvec_macros",
]
@@ -3389,7 +3391,7 @@ version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
- "indexmap 2.10.0",
+ "indexmap 2.11.0",
"serde",
"serde_spanned",
"toml_datetime",
@@ -3477,7 +3479,7 @@ version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
- "bitflags 2.9.1",
+ "bitflags 2.9.3",
"bytes",
"futures-util",
"http",
@@ -3587,14 +3589,14 @@ dependencies = [
[[package]]
name = "tx3-cardano"
-version = "0.11.1"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c7d4d7792ae33be71cf41512de7b40e5337cdef92b0b647aa611b6721dda974"
+checksum = "ca5f14e3e1b68b1bff81d58c891604a3087f34be70c2a2ad58a8605b6f15ed82"
dependencies = [
"hex",
"pallas",
"serde",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"trait-variant",
"tx3-lang",
"utxorpc 0.10.0",
@@ -3602,9 +3604,9 @@ dependencies = [
[[package]]
name = "tx3-lang"
-version = "0.11.1"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4faaad8f112e459a8e06c0ccd07756cf4b71a5d5545d1b95078c304dc74934fe"
+checksum = "7607218726810f53079b50a63ff4b5e25a8ccf53a82a80d7b6cc1815feec7a65"
dependencies = [
"bincode",
"hex",
@@ -3612,7 +3614,7 @@ dependencies = [
"pest",
"pest_derive",
"serde",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"trait-variant",
]
@@ -3628,7 +3630,7 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
- "thiserror 2.0.12",
+ "thiserror 2.0.16",
"tx3-lang",
"uuid",
]
@@ -3709,9 +3711,9 @@ checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
[[package]]
name = "url"
-version = "2.5.4"
+version = "2.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
dependencies = [
"form_urlencoded",
"idna",
@@ -3747,13 +3749,13 @@ dependencies = [
[[package]]
name = "utxorpc"
version = "0.11.0"
-source = "git+https://github.com/utxorpc/rust-sdk#b5f08b439e11331ccbef1d98657cd2ba3727b9fa"
+source = "git+https://github.com/utxorpc/rust-sdk#8760682ea8c37bbbd098dba638ccdd0d6902b949"
dependencies = [
"bytes",
"thiserror 1.0.69",
"tokio",
"tonic",
- "utxorpc-spec 0.15.0",
+ "utxorpc-spec 0.17.0",
]
[[package]]
@@ -3788,11 +3790,27 @@ dependencies = [
"tonic",
]
+[[package]]
+name = "utxorpc-spec"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d984ee351b308377e118135e638a5d544fdb0855f12a3b088d9dcaf0432052"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "pbjson",
+ "pbjson-types",
+ "prost",
+ "prost-types",
+ "serde",
+ "tonic",
+]
+
[[package]]
name = "uuid"
-version = "1.17.0"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
+checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
dependencies = [
"getrandom 0.3.3",
"js-sys",
@@ -3844,11 +3862,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
-version = "0.14.2+wasi-0.2.4"
+version = "0.14.3+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95"
dependencies = [
- "wit-bindgen-rt",
+ "wit-bindgen",
]
[[package]]
@@ -3987,11 +4005,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -4349,21 +4367,18 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
-version = "0.7.12"
+version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
+checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
[[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
+name = "wit-bindgen"
+version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
-dependencies = [
- "bitflags 2.9.1",
-]
+checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814"
[[package]]
name = "writeable"
@@ -4455,9 +4470,9 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.11.2"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
+checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
dependencies = [
"yoke",
"zerofrom",
diff --git a/docs/explorer.mdx b/docs/explorer.mdx
new file mode 100644
index 0000000..d3a4393
--- /dev/null
+++ b/docs/explorer.mdx
@@ -0,0 +1,35 @@
+---
+title: Explorer
+sidebar:
+ order: 4
+---
+
+The explorer is a terminal-based UI where you can interact with your wallets and blockchain data in real-time.
+
+## Usage
+
+```bash
+cshell explorer
+```
+
+## Features
+
+The explorer provides the following features:
+
+### Accounts Tab
+
+Displays a list of your wallets and their balances.
+
+### Blocks Tab
+
+Shows a real-time stream of new blocks as they are added to the blockchain.
+
+### Transactions Tab
+
+Displays a list of recent transactions. And it is possible to fetch older transactions typing the tx hash.
+
+## Keybindings
+
+- `q`: Quit the explorer
+- `Tab`: Switch between tabs
+- `?`: Show the help popup
diff --git a/docs/index.mdx b/docs/index.mdx
new file mode 100644
index 0000000..35c7aff
--- /dev/null
+++ b/docs/index.mdx
@@ -0,0 +1,60 @@
+---
+title: Quickstart
+sidebar:
+ order: 0
+---
+
+import { Steps, Tabs, TabItem, Cards, Card } from "@astrojs/starlight/components"
+
+In this guide we're going to learn how to go from zero to a running Cshell instance with the least amount of effort.
+
+
+1. ### Installation
+
+
+
+ You can use Homebrew to install the latest version of Cshell in Mac (both x86 / ARM64)
+
+ ```sh
+ brew install txpipe/tap/cshell
+ ```
+
+
+ You can install Cshell on linux system using the following command:
+
+ ```sh
+ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/txpipe/cshell/releases/latest/download/cshell-installer.sh | sh
+ ```
+
+
+ You can use Npm to install Cshell on your system:
+
+ ```sh
+ npm install @txpipe/cshell
+ ```
+
+
+
+2. ### Configuration
+
+ _Cshell_ requires a UtxoRPC and TRP provider, the UtxoRPC is to fetch on-chain data, and the TRP is to resolve and submit transactions. You can get one free instance on [demeter](https://demeter.run/). So when you have the UtxoRPC and TRP url, run the following command that will guide you through a set of questions to define a provider:
+
+ ```sh
+ cshell provider create
+ ```
+
+ With the provider configured, it is possible to create a wallet or import one. The following example shows how to create one.
+
+ ```sh
+ cshell wallet create
+ ```
+
+3. ### Running
+
+ Explore the commands in the docs or run `cshell --help`. The following command opens a GUI explorer using the default provider.
+
+ ```sh
+ cshell explorer
+ ```
+
+
diff --git a/docs/provider.mdx b/docs/provider.mdx
new file mode 100644
index 0000000..e5bf411
--- /dev/null
+++ b/docs/provider.mdx
@@ -0,0 +1,42 @@
+---
+title: Provider
+sidebar:
+ order: 1
+---
+
+import { Aside } from '@astrojs/starlight/components';
+
+Cshell uses [**UtxoRPC**](https://utxorpc.org) as its on-chain data provider. It connects to a UtxoRPC server to collect blockchain data and follow the tip. Any service that implements the UtxoRPC interface can act as a data provider for Cshell, for example, [**Dolos**](https://github.com/txpipe/dolos).
+
+UtxoRPC is used only for supplying on-chain data. For transaction resolution and submission, Cshell uses a TRP (Transaction Resolution Protocol) server. TRP, used with [**Tx3**](https://github.com/tx3-lang/tx3), exposes a JSON-RPC interface to resolve and submit transactions. Any application that implements that JSON-RPC interface can serve as Cshell's TRP provider, for example [**Hydra TRP**](https://github.com/tx3-lang/tx3-hydra).
+
+
+
+### Provider storage
+All cshell provider configurations are stored in a single file on your local machine:
+
+- File: **cshell.toml**
+- Location: In your user home directory (examples: **~/cshell.toml**)
+
+This file contains the definitions for every provider you create.
+
+## Usage
+When providers are available, create and configure a provider in Cshell using the **interactive** command below:
+
+```bash
+cshell provider create
+```
+
+You can manage providers using Cshell's provider commands. To see which provider commands are available, run the following:
+
+```bash
+cshell provider --help
+```
+
+And the `--help` flag can be used anywhere in Cshell. For example, after choosing the create command, you can check the options available for that command as well:
+
+```bash
+cshell provider create --help
+```
diff --git a/docs/usage.mdx b/docs/usage.mdx
new file mode 100644
index 0000000..a1c6194
--- /dev/null
+++ b/docs/usage.mdx
@@ -0,0 +1,52 @@
+---
+title: Usage
+sidebar:
+ order: 3
+---
+
+import { Aside } from '@astrojs/starlight/components';
+
+With Cshell fully configured ([provider](/cshell/provider) and [wallet](/cshell/wallet)), it's time to start using it to manage transactions or fetch on-chain data.
+
+You can execute any transaction in Cshell using [**tx3**](https://docs.txpipe.io/tx3). Cshell will call the TRP to resolve and submit the transaction.
+
+
+
+
+
+## Commands
+The commands below are used to handle transactions and fetch on-chain data.
+
+### Transactions
+You can manage transactions by using Cshell's `tx` or `transactions` commands. To see which tx commands are available, run the following:
+
+```bash
+cshell tx --help
+```
+
+Use the `--help` flag with any command to view its available options.
+
+```bash
+cshell tx invoke --help
+```
+
+### Search
+You can search by block or transactions using the commands search. To see which search commands are available, run the following
+
+
+
+```bash
+cshell search --help
+```
+
+Use the `--help` flag with any command to view its available options.
+
+```bash
+cshell search block --help
+```
diff --git a/docs/wallet.mdx b/docs/wallet.mdx
new file mode 100644
index 0000000..81876b6
--- /dev/null
+++ b/docs/wallet.mdx
@@ -0,0 +1,63 @@
+---
+title: Wallet
+sidebar:
+ order: 2
+---
+
+import { Aside } from '@astrojs/starlight/components';
+
+How cshell handles wallet creation, storage, and security. Understanding these concepts is crucial for managing your funds safely.
+
+### Wallet storage
+All cshell wallet configurations are stored in a single file on your local machine:
+
+- File: **cshell.toml**
+- Location: In your user home directory (examples: **~/cshell.toml**)
+
+This file contains the definitions for every wallet you create, import, or restore.
+
+### Security and encryption
+Cshell protects private keys using a password-based encryption model.
+
+- When you create a wallet you set a spending password.
+- The password is run through Argon2 to derive an encryption key, and that key is used with the `ChaCha20-Poly1305` cipher to encrypt the wallet’s private key.
+- **Your password is never stored on disk**, it exists only in memory when needed to sign a transaction.
+
+
+
+### Unsafe wallets (plain-text keys)
+Cshell supports an `--unsafe` option at creation time (wallet create --unsafe).
+
+- What it does: disables password protection and stores the private key in plain text inside cshell.toml.
+- Intended use: temporary, disposable wallets for development or testing only.
+
+
+
+### Importing vs restoring wallets
+Cshell supports both wallet import and wallet restore, these are different operations with different functional implications.
+
+- Import: creating read-only (watch-only) wallets.
+- Restore: recovering fully functional wallets using the mnemonic seed phrase.
+
+## Usage
+Create a wallet using the **interactive** command below:
+
+```bash
+cshell wallet create
+```
+
+You can manage wallets using Cshell's wallet commands. To see which wallet commands are available, run the following:
+
+```bash
+cshell wallet --help
+```
+
+And the `--help` flag can be used anywhere in Cshell. For example, after choosing the create command, you can check the options available for that command as well:
+
+```bash
+cshell wallet create --help
+```
diff --git a/src/explorer/event.rs b/src/explorer/event.rs
index 5d425a2..4f0395b 100644
--- a/src/explorer/event.rs
+++ b/src/explorer/event.rs
@@ -240,7 +240,7 @@ impl EventTask {
self.check_balances().await?;
}
TipEvent::Reset(point) => {
- self.send(Event::App(AppEvent::Reset(point.index)))?;
+ self.send(Event::App(AppEvent::Reset(point.slot)))?;
self.check_balances().await?;
}
}
diff --git a/src/explorer/mod.rs b/src/explorer/mod.rs
index 584f52f..a93b060 100644
--- a/src/explorer/mod.rs
+++ b/src/explorer/mod.rs
@@ -102,7 +102,7 @@ impl App {
events: EventHandler::new(context.clone()),
accounts_tab_state: AccountsTabState::default(),
blocks_tab_state: BlocksTabState::default(),
- transactions_tab_state: TransactionsTabState::default(),
+ transactions_tab_state: TransactionsTabState::new(Arc::clone(&context)),
}
}
@@ -173,7 +173,7 @@ impl App {
_ => self.accounts_tab_state.handle_key(&key),
},
SelectedTab::Blocks(_) => self.blocks_tab_state.handle_key(&key),
- SelectedTab::Transactions(_) => self.transactions_tab_state.handle_key(&key),
+ SelectedTab::Transactions(_) => self.transactions_tab_state.handle_key(&key).await,
}
}
}
@@ -197,13 +197,10 @@ impl App {
.update_scroll_state(self.chain.blocks.borrow().len());
self.transactions_tab_state
- .update_scroll_state(self.chain.blocks.borrow().iter().map(|b| b.tx_count).sum());
+ .update_blocks(Rc::clone(&self.chain.blocks));
self.selected_tab = match &self.selected_tab {
SelectedTab::Blocks(_) => SelectedTab::Blocks(BlocksTab::from(&*self)),
- SelectedTab::Transactions(_) => {
- SelectedTab::Transactions(TransactionsTab::from(&*self))
- }
x => x.clone(),
}
}
@@ -223,7 +220,7 @@ impl App {
.update_scroll_state(self.chain.blocks.borrow().len());
self.transactions_tab_state
- .update_scroll_state(self.chain.blocks.borrow().iter().map(|b| b.tx_count).sum());
+ .update_blocks(Rc::clone(&self.chain.blocks));
self.selected_tab = match &self.selected_tab {
SelectedTab::Blocks(_) => SelectedTab::Blocks(BlocksTab::from(&*self)),
@@ -233,7 +230,7 @@ impl App {
fn select_previous_tab(&mut self) {
self.selected_tab = match &self.selected_tab {
- SelectedTab::Accounts(_) => SelectedTab::Transactions(TransactionsTab::from(&*self)),
+ SelectedTab::Accounts(_) => SelectedTab::Transactions(TransactionsTab {}),
SelectedTab::Blocks(_) => SelectedTab::Accounts(AccountsTab::new(self.context.clone())),
SelectedTab::Transactions(_) => SelectedTab::Blocks(BlocksTab::from(&*self)),
}
@@ -242,7 +239,7 @@ impl App {
fn select_next_tab(&mut self) {
self.selected_tab = match &self.selected_tab {
SelectedTab::Accounts(_) => SelectedTab::Blocks(BlocksTab::from(&*self)),
- SelectedTab::Blocks(_) => SelectedTab::Transactions(TransactionsTab::from(&*self)),
+ SelectedTab::Blocks(_) => SelectedTab::Transactions(TransactionsTab {}),
SelectedTab::Transactions(_) => {
SelectedTab::Accounts(AccountsTab::new(self.context.clone()))
}
diff --git a/src/explorer/widgets/tabs/transactions.rs b/src/explorer/widgets/tabs/transactions.rs
index ae3a6f8..45692c6 100644
--- a/src/explorer/widgets/tabs/transactions.rs
+++ b/src/explorer/widgets/tabs/transactions.rs
@@ -1,7 +1,7 @@
-use std::{cell::RefCell, collections::VecDeque, rc::Rc};
+use std::{cell::RefCell, collections::VecDeque, rc::Rc, sync::Arc};
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
-use pallas::ledger::addresses::Address;
+use pallas::{interop::utxorpc::TxHash, ledger::addresses::Address};
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Margin, Rect},
@@ -14,33 +14,53 @@ use ratatui::{
};
use regex::Regex;
use tui_tree_widget::{Tree, TreeItem, TreeState};
-use utxorpc::spec::cardano::{
- self, big_int,
- certificate::Certificate,
- d_rep, metadatum, native_script, plutus_data,
- script::{self},
- stake_credential, AuxData, Datum, Metadatum, NativeScript, PlutusData, Redeemer,
- RedeemerPurpose, Script, Tx, TxInput, TxOutput, TxValidity, VKeyWitness, Withdrawal,
- WitnessSet,
+use utxorpc::spec::{
+ cardano::{
+ self, big_int,
+ certificate::Certificate,
+ d_rep, metadatum, native_script, plutus_data,
+ script::{self},
+ stake_credential, AuxData, Datum, Metadatum, NativeScript, PlutusData, Redeemer,
+ RedeemerPurpose, Script, Tx, TxInput, TxOutput, TxValidity, VKeyWitness, Withdrawal,
+ WitnessSet,
+ },
+ query,
};
use crate::{
- explorer::{App, ChainBlock},
+ explorer::{ChainBlock, ExplorerContext},
utils::AdaFormat,
};
-#[derive(Default)]
pub struct TransactionsTabState {
+ context: Arc,
+ blocks: Rc>>,
scroll_state: ScrollbarState,
table_state: TableState,
search_input: String,
input_mode: InputMode,
view_mode: ViewMode,
+ txs: Vec,
tx_selected: Option,
detail_state: TransactionsDetailState,
}
impl TransactionsTabState {
- pub fn handle_key(&mut self, key: &KeyEvent) {
+ pub fn new(context: Arc) -> Self {
+ Self {
+ context,
+ blocks: Rc::default(),
+ scroll_state: Default::default(),
+ table_state: Default::default(),
+ search_input: Default::default(),
+ input_mode: Default::default(),
+ view_mode: Default::default(),
+ txs: Default::default(),
+ tx_selected: Default::default(),
+ detail_state: Default::default(),
+ }
+ }
+
+ pub async fn handle_key(&mut self, key: &KeyEvent) {
match self.view_mode {
ViewMode::Normal => match self.input_mode {
InputMode::Normal => match (key.code, key.modifiers) {
@@ -53,7 +73,13 @@ impl TransactionsTabState {
}
(KeyCode::Esc, _) => {
if !self.search_input.is_empty() {
- self.search_input.clear()
+ self.search_input.clear();
+ self.txs = self
+ .blocks
+ .borrow()
+ .iter()
+ .flat_map(TxView::from_chain_block)
+ .collect();
}
}
(KeyCode::Enter, _) => {
@@ -73,6 +99,46 @@ impl TransactionsTabState {
}
KeyCode::Esc => self.input_mode = InputMode::Normal,
KeyCode::Enter => {
+ let mut txs: Vec = self
+ .blocks
+ .borrow()
+ .iter()
+ .flat_map(TxView::from_chain_block)
+ .collect();
+
+ if !self.search_input.is_empty() {
+ let input_regex = Regex::new(&self.search_input).unwrap();
+
+ txs.retain(|tx| {
+ input_regex.is_match(&tx.hash)
+ || input_regex.is_match(&tx.block_slot.to_string())
+ });
+
+ if txs.is_empty() {
+ if let Ok(v) = hex::decode(&self.search_input) {
+ if let Ok(tx_hash) = v.try_into() {
+ let tx_hash = TxHash::new(tx_hash);
+ if let Ok(Some(any_chain_tx)) =
+ self.context.provider.fetch_tx(tx_hash.to_vec()).await
+ {
+ if let Some(tx_view) =
+ TxView::from_any_chain_tx(&any_chain_tx)
+ {
+ txs.push(tx_view);
+ }
+ }
+ }
+ }
+ }
+
+ if !self.txs.is_empty() {
+ self.table_state.select_first();
+ self.input_mode = InputMode::Normal
+ }
+ }
+
+ self.txs = txs;
+
self.table_state.select_first();
self.input_mode = InputMode::Normal
}
@@ -87,12 +153,23 @@ impl TransactionsTabState {
}
}
- pub fn update_scroll_state(&mut self, len: usize) {
+ pub fn update_blocks(&mut self, blocks: Rc>>) {
+ self.blocks = blocks;
+ let len: usize = self.blocks.borrow().iter().map(|b| b.tx_count).sum();
self.scroll_state = self.scroll_state.content_length(
len.checked_mul(3)
.and_then(|v| v.checked_sub(2))
.unwrap_or(0),
- )
+ );
+
+ if self.search_input.is_empty() {
+ self.txs = self
+ .blocks
+ .borrow()
+ .iter()
+ .flat_map(TxView::from_chain_block)
+ .collect();
+ }
}
fn next_row(&mut self) {
@@ -124,15 +201,17 @@ impl TransactionsTabState {
#[derive(Clone)]
pub struct TransactionsTab {
- blocks: Rc>>,
-}
-impl From<&App> for TransactionsTab {
- fn from(value: &App) -> Self {
- Self {
- blocks: Rc::clone(&value.chain.blocks),
- }
- }
+ // blocks: Rc>>,
+ // context: Arc,
}
+// impl From<&App> for TransactionsTab {
+// fn from(value: &App) -> Self {
+// Self {
+// blocks: Rc::clone(&value.chain.blocks),
+// context: value.context.clone(),
+// }
+// }
+// }
#[derive(Clone, Default, PartialEq)]
enum InputMode {
@@ -188,18 +267,8 @@ impl StatefulWidget for TransactionsTab {
.collect::()
.style(Style::default().fg(Color::Green).bold())
.height(1);
- let mut txs: Vec =
- self.blocks.borrow().iter().flat_map(TxView::new).collect();
- if !state.search_input.is_empty() {
- let input_regex = Regex::new(&state.search_input).unwrap();
-
- txs.retain(|tx| {
- input_regex.is_match(&tx.hash)
- || input_regex.is_match(&tx.block_slot.to_string())
- });
- }
- let rows = txs.iter().enumerate().map(|(i, tx)| {
+ let rows = state.txs.iter().enumerate().map(|(i, tx)| {
let color = match i % 2 {
0 => Color::Black,
_ => Color::Reset,
@@ -246,15 +315,7 @@ impl StatefulWidget for TransactionsTab {
ViewMode::Detail => {
if state.tx_selected.is_none() {
let index = state.table_state.selected().unwrap();
-
- let txs: Vec = self
- .blocks
- .borrow()
- .iter()
- .flat_map(TxView::new_with_tx)
- .collect();
-
- state.tx_selected = Some(txs[index].clone());
+ state.tx_selected = Some(state.txs[index].clone());
}
TransactionsDetail::new(state.tx_selected.clone().unwrap()).render(
@@ -530,51 +591,68 @@ pub struct TxView {
block_hash: String,
}
impl TxView {
- pub fn new(chain_block: &ChainBlock) -> Vec {
- match &chain_block.body {
- Some(body) => body
- .tx
- .iter()
- .map(|tx| Self {
- hash: hex::encode(&tx.hash),
- certs: tx.certificates.len(),
- assets: tx.outputs.iter().map(|o| o.assets.len()).sum(),
- amount_ada: tx.outputs.iter().map(|o| o.coin).sum(),
- datum: tx.outputs.iter().any(|o| match &o.datum {
- Some(datum) => !datum.hash.is_empty(),
- None => false,
- }),
- tx: None,
+ pub fn from_chain_block(chain_block: &ChainBlock) -> Vec {
+ let body = match &chain_block.body {
+ Some(b) => b,
+ None => return Vec::new(),
+ };
+
+ body.tx
+ .iter()
+ .map(|tx| {
+ let hash = hex::encode(&tx.hash);
+ let certs = tx.certificates.len();
+ let assets = tx.outputs.iter().map(|o| o.assets.len()).sum();
+ let amount_ada = tx.outputs.iter().map(|o| o.coin).sum();
+ let datum = tx
+ .outputs
+ .iter()
+ .any(|o| o.datum.as_ref().is_some_and(|d| !d.hash.is_empty()));
+
+ TxView {
+ hash,
+ certs,
+ assets,
+ amount_ada,
+ datum,
+ // TODO: improve to not clone the whole tx
+ tx: Some(tx.clone()),
block_slot: chain_block.slot,
block_height: chain_block.number,
block_hash: hex::encode(&chain_block.hash),
- })
- .collect(),
- None => Default::default(),
- }
+ }
+ })
+ .collect()
}
- pub fn new_with_tx(chain_block: &ChainBlock) -> Vec {
- match &chain_block.body {
- Some(body) => body
- .tx
- .iter()
- .map(|tx| Self {
- hash: hex::encode(&tx.hash),
- certs: tx.certificates.len(),
- assets: tx.outputs.iter().map(|o| o.assets.len()).sum(),
- amount_ada: tx.outputs.iter().map(|o| o.coin).sum(),
- datum: tx.outputs.iter().any(|o| match &o.datum {
- Some(datum) => !datum.hash.is_empty(),
- None => false,
- }),
+ pub fn from_any_chain_tx(any_chain_tx: &query::AnyChainTx) -> Option {
+ let chain = any_chain_tx.chain.as_ref()?;
+ let block_ref = any_chain_tx.block_ref.as_ref()?;
+
+ match chain {
+ query::any_chain_tx::Chain::Cardano(tx) => {
+ let hash = hex::encode(&tx.hash);
+ let certs = tx.certificates.len();
+ let assets = tx.outputs.iter().map(|o| o.assets.len()).sum();
+ let amount_ada = tx.outputs.iter().map(|o| o.coin).sum();
+ let datum = tx
+ .outputs
+ .iter()
+ .any(|o| o.datum.as_ref().is_some_and(|d| !d.hash.is_empty()));
+
+ Some(TxView {
+ hash,
+ certs,
+ assets,
+ amount_ada,
+ datum,
+ // TODO: improve to not clone the whole tx
tx: Some(tx.clone()),
- block_slot: chain_block.slot,
- block_height: chain_block.number,
- block_hash: hex::encode(&chain_block.hash),
+ block_slot: block_ref.slot,
+ block_height: block_ref.height,
+ block_hash: hex::encode(&block_ref.hash),
})
- .collect(),
- None => Default::default(),
+ }
}
}
}
diff --git a/src/main.rs b/src/main.rs
index 61c2789..b7c83cb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,6 +8,7 @@ mod explorer;
mod output;
mod provider;
mod reports;
+mod search;
mod store;
mod tx;
mod types;
@@ -65,6 +66,9 @@ enum Commands {
/// Explore the blockchain
#[command()]
Explorer(explorer::Args),
+
+ /// Search on chain data
+ Search(search::Args),
}
#[derive(Clone, ValueEnum)]
@@ -131,6 +135,7 @@ async fn run_command() -> anyhow::Result<()> {
Commands::Tx(args) => tx::run(args, &ctx).await,
Commands::Wallet(args) => wallet::run(args, &mut ctx).await,
Commands::Explorer(args) => explorer::run(args, &ctx).await,
+ Commands::Search(args) => search::run(args, &mut ctx).await,
};
ctx.store.write()?;
diff --git a/src/provider/types.rs b/src/provider/types.rs
index e81cc05..0981e65 100644
--- a/src/provider/types.rs
+++ b/src/provider/types.rs
@@ -6,8 +6,11 @@ use pallas::ledger::addresses::Address;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use utxorpc::{
- spec::query::any_utxo_pattern::UtxoPattern, CardanoQueryClient, CardanoSubmitClient,
- CardanoSyncClient, ClientBuilder, InnerService,
+ spec::{
+ query::{any_utxo_pattern::UtxoPattern, AnyChainTx, ReadTxRequest},
+ sync::{AnyChainBlock, BlockRef, FetchBlockRequest},
+ },
+ CardanoQueryClient, CardanoSubmitClient, CardanoSyncClient, ClientBuilder, InnerService,
};
use crate::{
@@ -70,7 +73,7 @@ impl Provider {
Some(blockref) => {
println!(
"Successfull request, block tip at slot {} and hash {}.",
- blockref.index,
+ blockref.slot,
hex::encode(blockref.hash)
)
}
@@ -286,6 +289,48 @@ impl Provider {
Ok(client.submit(tx, vec![]).await?)
}
+
+ pub async fn fetch_block(&self, refs: Vec<(Vec, u64)>) -> Result> {
+ let mut client: utxorpc::CardanoSyncClient = self.client().await?;
+
+ let refs = refs
+ .iter()
+ .map(|(hash, index)| BlockRef {
+ hash: hash.clone().into(),
+ slot: *index,
+ ..Default::default()
+ })
+ .collect();
+
+ let request = FetchBlockRequest {
+ r#ref: refs,
+ ..Default::default()
+ };
+ let response = client
+ .fetch_block(request)
+ .await
+ .map_err(|err| anyhow::Error::msg(format!("Fetch block. {}", err.code())))?
+ .into_inner();
+
+ Ok(response.block)
+ }
+
+ pub async fn fetch_tx(&self, hash: Vec) -> Result