diff --git a/web/explorer/Cargo.lock b/web/explorer/Cargo.lock index 5211f4a77..c89483ca7 100644 --- a/web/explorer/Cargo.lock +++ b/web/explorer/Cargo.lock @@ -1,2300 +1,2300 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arrayvec" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "askama" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134" dependencies = [ "askama_derive", "askama_escape", "askama_shared", ] [[package]] name = "askama_derive" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522" dependencies = [ "askama_shared", "proc-macro2", "syn 1.0.109", ] [[package]] name = "askama_escape" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" [[package]] name = "askama_shared" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d6083ccb191711e9c2b80b22ee24a8381a18524444914c746d4239e21d1afaf" dependencies = [ "askama_escape", "humansize", "nom", "num-traits", "percent-encoding", "proc-macro2", "quote", "serde", "syn 1.0.109", "toml", ] [[package]] name = "async-trait" version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", ] [[package]] name = "autocfg" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "axum" version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43" dependencies = [ "async-trait", "axum-core", "bitflags 1.3.2", "bytes", "futures-util", "http", "http-body", "hyper", "itoa", "matchit", "memchr", "mime", "percent-encoding", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", "tower", "tower-http", "tower-layer", "tower-service", ] [[package]] name = "axum-core" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc" dependencies = [ "async-trait", "bytes", "futures-util", "http", "http-body", "mime", "tower-layer", "tower-service", ] [[package]] name = "backtrace" version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bech32" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1" [[package]] name = "bitcoin" version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aefc9be9f17185f4ebccae6575d342063f775924d57df0000edb1880c0fb7095" dependencies = [ "bech32", "bitcoin_hashes", "secp256k1", ] [[package]] name = "bitcoin_hashes" version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1" [[package]] name = "bitcoinsuite-chronik-client" version = "0.1.0" -source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=dc6d80b#dc6d80b293812c49018d2faf4e051da8f62983d9" +source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=6d2d946#6d2d946f793b1fc6265a7b3f8f73420811e1dae3" dependencies = [ "bitcoinsuite-core", "bitcoinsuite-error", "hex", "prost", "prost-build", "reqwest", "thiserror", "tokio", ] [[package]] name = "bitcoinsuite-core" version = "0.1.0" -source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=dc6d80b#dc6d80b293812c49018d2faf4e051da8f62983d9" +source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=6d2d946#6d2d946f793b1fc6265a7b3f8f73420811e1dae3" dependencies = [ "bs58", "bytes", "digest", "hex", "hex-literal", "once_cell", "regex", "ripemd", "secrecy", "serde", "sha-1", "sha2", "thiserror", ] [[package]] name = "bitcoinsuite-error" version = "0.1.0" -source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=dc6d80b#dc6d80b293812c49018d2faf4e051da8f62983d9" +source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=6d2d946#6d2d946f793b1fc6265a7b3f8f73420811e1dae3" dependencies = [ "bitcoinsuite-error-derive", "eyre", "lazy_static", "stable-eyre", ] [[package]] name = "bitcoinsuite-error-derive" version = "0.1.0" -source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=dc6d80b#dc6d80b293812c49018d2faf4e051da8f62983d9" +source = "git+https://github.com/LogosFoundation/bitcoinsuite?rev=6d2d946#6d2d946f793b1fc6265a7b3f8f73420811e1dae3" dependencies = [ "convert_case", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" version = "0.19.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" dependencies = [ "funty", "radium", "tap", "wyz", ] [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bs58" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] [[package]] name = "cc" version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-targets 0.52.4", ] [[package]] name = "chrono-humanize" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8164ae3089baf04ff71f32aeb70213283dcd236dce8bc976d00b17a458f5f71c" dependencies = [ "chrono", ] [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "convert_case" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" dependencies = [ "unicode-segmentation", ] [[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "either" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "explorer-exe" version = "0.1.0" dependencies = [ "axum", "bitcoinsuite-chronik-client", "bitcoinsuite-error", "explorer-server", "futures", "tokio", ] [[package]] name = "explorer-server" version = "0.1.0" dependencies = [ "askama", "axum", "base64 0.13.1", "bitcoin", "bitcoinsuite-chronik-client", "bitcoinsuite-core", "bitcoinsuite-error", "chrono", "chrono-humanize", "eyre", "futures", "hex", "humansize", "maud", "num-format", "qrcode-generator", "serde", "serde_json", "thiserror", "tokio", "toml", "tower-http", ] [[package]] name = "eyre" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", ] [[package]] name = "fastrand" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fdeflate" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", ] [[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.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "funty" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", ] [[package]] name = "futures-sink" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", "http", "indexmap", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "home" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "html-escape" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" dependencies = [ "utf8-width", ] [[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-body" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", "pin-project-lite", ] [[package]] name = "http-range-header" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humansize" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" [[package]] name = "hyper" version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", "want", ] [[package]] name = "hyper-tls" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", "hyper", "native-tls", "tokio", "tokio-native-tls", ] [[package]] name = "iana-time-zone" version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "idna" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] name = "image" version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", "color_quant", "num-traits", "png", ] [[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lexical-core" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec 0.5.2", "bitflags 1.3.2", "cfg-if", "ryu", "static_assertions", ] [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "matchit" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" [[package]] name = "maud" version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59d449907de7d1ae5b290cbaf9ea34a8a7df3fa5db027664bb55bb2b0fc1407c" dependencies = [ "maud_htmlescape", "maud_macros", ] [[package]] name = "maud_htmlescape" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0555daa37f94b5ebb206faf8cdc7b260c2aa371b509e929de9a1e37416d97fa6" [[package]] name = "maud_macros" version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6896f8e8cdcea80b99ac0f1f7a233708e640737a8517448f50500e401bb8d76" dependencies = [ "maud_htmlescape", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", ] [[package]] name = "miniz_oxide" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", ] [[package]] name = "mio" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", "windows-sys 0.48.0", ] [[package]] name = "multimap" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "native-tls" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "nom" version = "6.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" dependencies = [ "bitvec", "funty", "lexical-core", "memchr", "version_check", ] [[package]] name = "num-format" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ "arrayvec 0.7.4", "itoa", ] [[package]] name = "num-traits" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "object" version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.5.0", "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 2.0.58", ] [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets 0.48.5", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", "indexmap", ] [[package]] name = "pin-project" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", ] [[package]] name = "pin-project-lite" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[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.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "png" version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] [[package]] name = "prettyplease" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" dependencies = [ "proc-macro2", "syn 1.0.109", ] [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", "syn 1.0.109", "version_check", ] [[package]] name = "proc-macro-error-attr" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", "version_check", ] [[package]] name = "proc-macro2" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "prost" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", "prost-derive", ] [[package]] name = "prost-build" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" dependencies = [ "bytes", "heck", "itertools", "lazy_static", "log", "multimap", "petgraph", "prettyplease", "prost", "prost-types", "regex", "syn 1.0.109", "tempfile", "which", ] [[package]] name = "prost-derive" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "prost-types" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ "prost", ] [[package]] name = "qrcode-generator" version = "4.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d06cb9646c7a14096231a2474d7f21e5e8c13de090c68d13bde6157cfe7f159" dependencies = [ "html-escape", "image", "qrcodegen", ] [[package]] name = "qrcodegen" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" [[package]] name = "quote" -version = "1.0.36" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "radium" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" [[package]] name = "redox_syscall" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", "http", "http-body", "hyper", "hyper-tls", "ipnet", "js-sys", "log", "mime", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", "winreg", ] [[package]] name = "ripemd" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ "digest", ] [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] [[package]] name = "rustls-pemfile" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64 0.21.7", ] [[package]] name = "ryu" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "secp256k1" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb" dependencies = [ "secp256k1-sys", ] [[package]] name = "secp256k1-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2" dependencies = [ "cc", ] [[package]] name = "secrecy" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ "zeroize", ] [[package]] name = "security-framework" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "serde" version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", ] [[package]] name = "serde_json" version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", "serde", ] [[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 = "sha-1" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "signal-hook-registry" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "simd-adler32" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "stable-eyre" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556fec8c2da34c70b75f16d88df8a8cd7e652e567ff097b7e9df0022c8695cc4" dependencies = [ "backtrace", "eyre", "indenter", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[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.58" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "sync_wrapper" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "system-configuration" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", "rustix", "windows-sys 0.52.0", ] [[package]] name = "thiserror" version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", ] [[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-util" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", "tracing", ] [[package]] name = "toml" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] [[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", "tokio", "tower-layer", "tower-service", "tracing", ] [[package]] name = "tower-http" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ "bitflags 1.3.2", "bytes", "futures-core", "futures-util", "http", "http-body", "http-range-header", "httpdate", "mime", "mime_guess", "percent-encoding", "pin-project-lite", "tokio", "tokio-util", "tower", "tower-layer", "tower-service", ] [[package]] name = "tower-layer" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" [[package]] name = "tower-service" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "url" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] [[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ "try-lock", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn 2.0.58", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", "home", "once_cell", "rustix", ] [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets 0.52.4", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[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.4", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ "windows_aarch64_gnullvm 0.52.4", "windows_aarch64_msvc 0.52.4", "windows_i686_gnu 0.52.4", "windows_i686_msvc 0.52.4", "windows_x86_64_gnu 0.52.4", "windows_x86_64_gnullvm 0.52.4", "windows_x86_64_msvc 0.52.4", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winreg" version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "wyz" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" [[package]] name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/web/explorer/explorer-exe/Cargo.toml b/web/explorer/explorer-exe/Cargo.toml index 9a8f82da6..f1d3879ab 100644 --- a/web/explorer/explorer-exe/Cargo.toml +++ b/web/explorer/explorer-exe/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "explorer-exe" version = "0.1.0" edition = "2021" [dependencies] -bitcoinsuite-chronik-client = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "dc6d80b" } -bitcoinsuite-error = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "dc6d80b" } +bitcoinsuite-chronik-client = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "6d2d946" } +bitcoinsuite-error = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "6d2d946" } explorer-server = { path = "../explorer-server" } tokio = { version = "1.14", features = ["full"] } futures = "0.3" axum = "0.5.7" diff --git a/web/explorer/explorer-exe/config.dist.toml b/web/explorer/explorer-exe/config.dist.toml index dee29d41f..c0b9e418f 100644 --- a/web/explorer/explorer-exe/config.dist.toml +++ b/web/explorer/explorer-exe/config.dist.toml @@ -1,2 +1,2 @@ host = "0.0.0.0:3035" -chronik_api_url = "https://chronik.fabien.cash" +chronik_api_url = "https://chronik-native1.fabien.cash" diff --git a/web/explorer/explorer-server/Cargo.toml b/web/explorer/explorer-server/Cargo.toml index e0d52e266..856dccc62 100644 --- a/web/explorer/explorer-server/Cargo.toml +++ b/web/explorer/explorer-server/Cargo.toml @@ -1,29 +1,29 @@ [package] name = "explorer-server" version = "0.1.0" authors = ["tobiasruck "] edition = "2021" [dependencies] -bitcoinsuite-chronik-client = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "dc6d80b" } -bitcoinsuite-error = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "dc6d80b" } -bitcoinsuite-core = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "dc6d80b" } +bitcoinsuite-chronik-client = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "6d2d946" } +bitcoinsuite-error = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "6d2d946" } +bitcoinsuite-core = { git = "https://github.com/LogosFoundation/bitcoinsuite", rev = "6d2d946" } bitcoin = "0.25" maud = "0.22" tokio = { version = "1.14", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" hex = "0.4" futures = "0.3" num-format = "0.4" chrono = "0.4" chrono-humanize = "0.1.1" base64 = "0.13" qrcode-generator = "4.0" thiserror = "1.0" toml = "0.5" askama = "0.10.5" humansize = "1.1.1" eyre = "0.6" axum = "0.5.7" tower-http = { version = "0.3.4", features = ["fs"] } diff --git a/web/explorer/explorer-server/code/txs.js b/web/explorer/explorer-server/code/txs.js index 12b3f3864..c8c38531f 100644 --- a/web/explorer/explorer-server/code/txs.js +++ b/web/explorer/explorer-server/code/txs.js @@ -1,221 +1,236 @@ const renderHash = data => { let minifiedHash = minifyBlockID(data.txHash); if (data.blockHeight === 0) { return ( '' + minifiedHash + '' ); } else { return '' + minifiedHash + ''; } }; var today = Date.now() / 1000; var fiveYearsAgo = today - 157800000; var xecDate = 1605441600; var bchDate = 1502193600; const renderSize = size => formatByteSize(size); const renderInput = data => { const txDate = data.timestamp; let xecIcon = ''; let bchIcon = ''; let fiveIcon = ''; if (txDate < xecDate) { xecIcon = '
Pre-XEC
(Nov 15, 2020)
'; } if (txDate < bchDate) { bchIcon = '
Pre-BCH
(Aug 8, 2017)
'; } if (txDate < fiveYearsAgo) { fiveIcon = '
Over Five
Years Old
'; } return ( '
' + xecIcon + fiveIcon + bchIcon + `
${data.numInputs}
` ); }; const renderOutput = (satsOutput, _type, row) => { if (row.token) { var ticker = ''; return renderAmount(row.stats.tokenOutput, row.token.decimals) + ticker; } return ( '
' + renderSats(row.stats.satsOutput) + '
' ); }; const updateLoading = status => { if (status) { $('#txs-table > tbody').addClass('blur'); $('.loader__container--fullpage').removeClass('hidden'); $('#pagination').addClass('hidden'); $('#footer').addClass('hidden'); } else { $('#txs-table > tbody').removeClass('blur'); $('.loader__container--fullpage').addClass('hidden'); $('#pagination').removeClass('hidden'); $('#footer').removeClass('hidden'); } }; // UI actions const goToPage = (event, page) => { event.preventDefault(); reRenderPage({ page }); }; // UI presentation elements const datatable = () => { const blockHash = $('#block-hash').text(); $('#txs-table').DataTable({ searching: false, lengthMenu: [25, 50, 100, 200], pageLength: DEFAULT_ROWS_PER_PAGE, language: { loadingRecords: '', zeroRecords: '', emptyTable: '', }, - ajax: `/api/block/${blockHash}/transactions`, order: [], responsive: { details: { type: 'column', target: -1, }, }, columnDefs: [ { className: 'dtr-control', orderable: false, targets: -1, }, ], columns: [ { data: { txHash: 'txHash', blockHeight: 'blockHeight' }, title: 'ID', className: 'hash', render: renderHash, orderable: false, }, { data: 'size', title: 'Size', render: renderSize, className: 'text-right', orderSequence: ['desc', 'asc'], type: 'file-size', targets: 0, }, { name: 'fee', title: 'Fee', css: 'fee', render: renderFee, className: 'text-right', orderSequence: ['desc', 'asc'], type: 'html-num-fmt', }, { data: { numInputs: 'numInputs' }, title: 'Inputs', className: 'text-right', render: renderInput, orderSequence: ['desc', 'asc'], }, { data: 'numOutputs', title: 'Outputs', className: 'text-right', orderSequence: ['desc', 'asc'], }, { data: 'satsOutput', title: 'Output Amount', render: renderOutput, className: 'text-right', orderSequence: ['desc', 'asc'], }, { name: 'responsive', render: () => '' }, ], }); params = window.state.getParameters(); - $('#txs-table').dataTable().api().page.len(params.rows); + const page_size = params.rows; + $('#txs-table').dataTable().api().page.len(page_size); + refreshTxsTablePage(0); }; // events $(window).resize(() => { const { currentPage, pageArray } = window.pagination.generatePaginationUIParams(); window.pagination.generatePaginationUI(currentPage, pageArray); $('#blocks-table').DataTable().responsive.rebuild(); $('#blocks-table').DataTable().responsive.recalc(); }); $('#txs-table').on('init.dt', () => { $('.datatable__length-placeholder').remove(); }); $('#txs-table').on('length.dt', (e, settings, rows) => { params = window.state.getParameters(); if (params.rows !== rows) { reRenderPage({ rows }); } }); $('#txs-table').on('xhr.dt', () => { updateLoading(false); }); +function refreshTxsTablePage(page) { + const blockHash = $('#block-hash').text(); + params = window.state.getParameters(); + const page_size = params.rows; + + $('#txs-table') + .dataTable() + .api() + .ajax.url(`/api/block/${blockHash}/transactions/${page}/${page_size}`) + .load(); +} + // Basically a fake refresh, dynamically updates everything // according to new params // updates: URL, table and pagination const reRenderPage = params => { if (params) { window.state.updateParameters(params); if (params.page) { // DataTable pages start at index 0, so we oblige $('#txs-table') .DataTable() .page(params.page - 1) .draw(false); + + refreshTxsTablePage(params.page - 1); } } const { currentPage, pageArray } = window.pagination.generatePaginationUIParams(); window.pagination.generatePaginationUI(currentPage, pageArray); }; // main $(document).ready(() => { // init all UI elements datatable(); // global state update reRenderPage(); }); diff --git a/web/explorer/explorer-server/src/api.rs b/web/explorer/explorer-server/src/api.rs index f86587e8b..5c769c725 100644 --- a/web/explorer/explorer-server/src/api.rs +++ b/web/explorer/explorer-server/src/api.rs @@ -1,226 +1,232 @@ use std::collections::HashMap; use bitcoinsuite_chronik_client::proto::{ - Block, SlpGenesisInfo, Token, Tx, TxHistoryPage, + token_type, Block, GenesisInfo, TokenInfo, TokenType, Tx, TxHistoryPage, }; use bitcoinsuite_core::CashAddress; use bitcoinsuite_error::Result; +use eyre::eyre; use crate::{ blockchain::to_be_hex, server_primitives::{JsonToken, JsonTx, JsonTxStats}, }; +pub fn token_type_to_int(token_type_in: &Option) -> Result { + let token_type = token_type_in + .clone() + .ok_or_else(|| eyre!("Malformed token.token_type"))? + .token_type + .ok_or_else(|| eyre!("Malformed token.token_type.token_type"))?; + + match token_type { + token_type::TokenType::Slp(slp) => Ok(slp), + token_type::TokenType::Alp(alp) => Ok(alp), + } +} + pub fn tokens_to_json( - tokens: &HashMap, + tokens: &HashMap, ) -> Result> { let mut json_tokens = HashMap::new(); for (token_id, token) in tokens.iter() { - if let Some(slp_tx_data) = &token.slp_tx_data { - if let (Some(slp_meta), Some(genesis_info)) = - (&slp_tx_data.slp_meta, &slp_tx_data.genesis_info) - { - let token_ticker = - String::from_utf8_lossy(&genesis_info.token_ticker) - .to_string(); - let token_name = - String::from_utf8_lossy(&genesis_info.token_name) - .to_string(); - - let json_token = JsonToken { - token_id: token_id.clone(), - token_type: slp_meta.token_type, - token_ticker, - token_name, - decimals: genesis_info.decimals, - }; - json_tokens.insert(token_id.clone(), json_token.clone()); - } + if let Some(genesis_info) = &token.genesis_info { + let token_ticker = + String::from_utf8_lossy(&genesis_info.token_ticker).to_string(); + let token_name = + String::from_utf8_lossy(&genesis_info.token_name).to_string(); + + let token_type = token_type_to_int(&token.token_type)?; + + let json_token = JsonToken { + token_id: token_id.clone(), + token_type, + token_ticker, + token_name, + decimals: genesis_info.decimals, + }; + json_tokens.insert(token_id.clone(), json_token.clone()); } } Ok(json_tokens) } pub fn tx_history_to_json( address: &CashAddress, address_tx_history: TxHistoryPage, json_tokens: &HashMap, ) -> Result> { let mut json_txs = Vec::new(); let address_bytes = address.to_script().bytecode().to_vec(); for tx in address_tx_history.txs.iter() { let (block_height, timestamp) = match &tx.block { Some(block) => (Some(block.height), block.timestamp), None => (None, tx.time_first_seen), }; - let (token_id, token) = match &tx.slp_tx_data { - Some(slp_tx_data) => { - let slp_meta = - slp_tx_data.slp_meta.as_ref().expect("Impossible"); - let token_id = hex::encode(&slp_meta.token_id); + let (token_id, token) = match &tx.token_entries.get(0) { + Some(token_entry) => { + let token_id = hex::encode(&token_entry.token_id); let json_token = json_tokens.get(&token_id); match json_token { Some(json_token) => { (Some(token_id.clone()), Some(json_token.clone())) } None => (Some(token_id.clone()), None), } } None => (None, None), }; let stats = calc_tx_stats(tx, Some(&address_bytes)); json_txs.push(JsonTx { tx_hash: to_be_hex(&tx.txid), block_height, timestamp, is_coinbase: tx.is_coinbase, size: tx.size as i32, num_inputs: tx.inputs.len() as u32, num_outputs: tx.outputs.len() as u32, stats, token_id, token, }); } Ok(json_txs) } pub fn block_txs_to_json( block: Block, - tokens_by_hex: &HashMap, + block_txs: TxHistoryPage, + tokens_by_hex: &HashMap, ) -> Result> { let mut json_txs = Vec::new(); - for tx in block.txs.iter() { + for tx in block_txs.txs.iter() { let (block_height, timestamp) = match &block.block_info { Some(block_info) => (Some(block_info.height), block_info.timestamp), None => (None, 0), }; - let (token_id, token) = match &tx.slp_tx_data { - Some(slp_tx_data) => { - let slp_meta = - slp_tx_data.slp_meta.as_ref().expect("Impossible"); - let token_id_hex = hex::encode(&slp_meta.token_id); + let (token_id, token) = match &tx.token_entries.get(0) { + Some(token_entry) => { + let token_id_hex = hex::encode(&token_entry.token_id); let genesis_info = match tokens_by_hex.get(&token_id_hex) { - Some(token) => token - .slp_tx_data - .as_ref() - .expect("Impossible") - .genesis_info - .as_ref(), + Some(token) => token.genesis_info.as_ref(), None => None, }; - let default_genesis_info = SlpGenesisInfo::default(); + let default_genesis_info = GenesisInfo::default(); let genesis_info = match genesis_info { Some(genesis_info) => genesis_info, None => { eprintln!( "No genesis info for token ID {}", token_id_hex ); &default_genesis_info } }; let token_ticker = String::from_utf8_lossy(&genesis_info.token_ticker) .to_string(); let token_name = String::from_utf8_lossy(&genesis_info.token_name) .to_string(); ( Some(token_id_hex), Some(JsonToken { - token_id: to_be_hex(&slp_meta.token_id), - token_type: slp_meta.token_type, + token_id: to_be_hex(&token_entry.token_id.as_bytes()), + token_type: token_type_to_int(&token_entry.token_type)?, token_ticker, token_name, decimals: genesis_info.decimals, }), ) } None => (None, None), }; let stats = calc_tx_stats(tx, None); json_txs.push(JsonTx { tx_hash: to_be_hex(&tx.txid), block_height, timestamp, is_coinbase: tx.is_coinbase, size: tx.size as i32, num_inputs: tx.inputs.len() as u32, num_outputs: tx.outputs.len() as u32, stats, token_id, token, }); } Ok(json_txs) } pub fn calc_tx_stats(tx: &Tx, address_bytes: Option<&[u8]>) -> JsonTxStats { let sats_input = tx.inputs.iter().map(|input| input.value).sum(); let sats_output = tx.outputs.iter().map(|output| output.value).sum(); + let token_input: i128 = tx .inputs .iter() - .filter_map(|input| input.slp_token.as_ref()) + .filter_map(|input| input.token.as_ref()) .map(|token| token.amount as i128) .sum(); let token_output: i128 = tx .outputs .iter() - .filter_map(|output| output.slp_token.as_ref()) + .filter_map(|output| output.token.as_ref()) .map(|token| token.amount as i128) .sum(); - let does_burn_slp = tx.inputs.iter().any(|input| input.slp_burn.is_some()); + let does_burn_slp = tx + .token_entries + .iter() + .any(|entry| entry.actual_burn_amount.parse::().unwrap() > 0); let mut delta_sats: i64 = 0; let mut delta_tokens: i64 = 0; for input in &tx.inputs { if let Some(address_bytes) = address_bytes { if address_bytes != input.output_script { continue; } } delta_sats -= input.value; - if let Some(slp) = &input.slp_token { + if let Some(slp) = &input.token { delta_tokens -= slp.amount as i64; } } for output in &tx.outputs { if let Some(address_bytes) = address_bytes { if address_bytes != output.output_script { continue; } } delta_sats += output.value; - if let Some(slp) = &output.slp_token { + if let Some(slp) = &output.token { delta_tokens += slp.amount as i64; } } JsonTxStats { sats_input, sats_output, delta_sats, delta_tokens, token_input, token_output, does_burn_slp, } } diff --git a/web/explorer/explorer-server/src/server.rs b/web/explorer/explorer-server/src/server.rs index 3b4b7626d..351ae5c10 100644 --- a/web/explorer/explorer-server/src/server.rs +++ b/web/explorer/explorer-server/src/server.rs @@ -1,591 +1,683 @@ use std::path::PathBuf; use std::{ borrow::Cow, collections::{hash_map::Entry, HashMap, HashSet}, }; use askama::Template; use axum::{response::Redirect, routing::get, Router}; use bitcoinsuite_chronik_client::proto::{ - SlpTokenType, SlpTxType, Token, Utxo, + token_type, AlpTokenType, ScriptUtxo, SlpTokenType, TokenInfo, TokenTxType, + TokenType, }; use bitcoinsuite_chronik_client::{proto::OutPoint, ChronikClient}; use bitcoinsuite_core::{CashAddress, Hashed, Sha256d}; use bitcoinsuite_error::Result; use chrono::{TimeZone, Utc}; use eyre::{bail, eyre}; use futures::future; use crate::{ api::{ block_txs_to_json, calc_tx_stats, tokens_to_json, tx_history_to_json, }, blockchain::{ calculate_block_difficulty, cash_addr_to_script_type_payload, from_be_hex, to_be_hex, to_legacy_address, }, chain::Chain, server_http::{ address, address_qr, block, block_height, blocks, data_address_txs, data_block_txs, data_blocks, search, serve_files, tx, }, server_primitives::{ JsonBalance, JsonBlock, JsonBlocksResponse, JsonTxsResponse, JsonUtxo, }, templating::{ AddressTemplate, BlockTemplate, BlocksTemplate, TransactionTemplate, }, }; pub struct Server { chronik: ChronikClient, base_dir: PathBuf, satoshi_addr_prefix: &'static str, tokens_addr_prefix: &'static str, } impl Server { pub async fn setup( chronik: ChronikClient, base_dir: PathBuf, chain: Chain, ) -> Result { Ok(Server { chronik, base_dir, satoshi_addr_prefix: match chain { Chain::Mainnet => "ecash", Chain::Testnet => "ectest", Chain::Regtest => "ecregtest", }, tokens_addr_prefix: "etoken", }) } pub fn router(&self) -> Router { Router::new() .route("/", get(blocks)) .route("/tx/:hash", get(tx)) .route("/blocks", get(blocks)) .route("/block/:hash", get(block)) .route("/block-height/:height", get(block_height)) .route("/address/:hash", get(address)) .route("/address-qr/:hash", get(address_qr)) .route("/search/:query", get(search)) .route("/api/blocks/:start_height/:end_height", get(data_blocks)) - .route("/api/block/:hash/transactions", get(data_block_txs)) + .route( + "/api/block/:hash/transactions/:page/:page_size", + get(data_block_txs), + ) .route("/api/address/:hash/transactions", get(data_address_txs)) .nest("/code", serve_files(&self.base_dir.join("code"))) .nest("/assets", serve_files(&self.base_dir.join("assets"))) .nest( "/favicon.ico", serve_files(&self.base_dir.join("assets").join("favicon.png")), ) } } impl Server { pub async fn blocks(&self) -> Result { let blockchain_info = self.chronik.blockchain_info().await?; let blocks_template = BlocksTemplate { last_block_height: blockchain_info.tip_height as u32, }; Ok(blocks_template.render().unwrap()) } } impl Server { + fn is_unknown_slp(token_type_in: &Option) -> Result { + let token_type = token_type_in + .clone() + .ok_or_else(|| eyre!("Malformed token.token_type"))? + .token_type + .ok_or_else(|| eyre!("Malformed token.token_type.token_type"))?; + + let is_unknown_slp = match token_type { + token_type::TokenType::Slp(slp) => { + let slp_token_type = SlpTokenType::from_i32(slp) + .ok_or_else(|| eyre!("Malformed SlpTokenType"))?; + match slp_token_type { + SlpTokenType::None => true, + _ => false, + } + } + _ => false, + }; + + Ok(is_unknown_slp) + } + pub async fn data_blocks( &self, start_height: i32, end_height: i32, ) -> Result { let blocks = self.chronik.blocks(start_height, end_height).await?; let mut json_blocks = Vec::with_capacity(blocks.len()); for block in blocks.into_iter().rev() { json_blocks.push(JsonBlock { hash: to_be_hex(&block.hash), height: block.height, timestamp: block.timestamp, difficulty: calculate_block_difficulty(block.n_bits), size: block.block_size, num_txs: block.num_txs, }); } Ok(JsonBlocksResponse { data: json_blocks }) } pub async fn data_block_txs( &self, block_hex: &str, + page: usize, + page_size: usize, ) -> Result { let block_hash = Sha256d::from_hex_be(block_hex)?; let block = self.chronik.block_by_hash(&block_hash).await?; + let block_txs = self + .chronik + .block_txs_by_hash_with_page_size(&block_hash, page, page_size) + .await?; - let token_ids = block + let token_ids = block_txs .txs .iter() .filter_map(|tx| { - let slp_tx_data = tx.slp_tx_data.as_ref()?; - let slp_meta = slp_tx_data.slp_meta.as_ref()?; - if slp_meta.token_type() == SlpTokenType::UnknownTokenType { + let token_entry = tx.token_entries.get(0)?; + if Self::is_unknown_slp(&token_entry.token_type).ok()? { return None; } Some( - Sha256d::from_slice_be(&slp_meta.token_id) + Sha256d::from_hex_be(&token_entry.token_id) .expect("Impossible"), ) }) .collect::>(); let tokens_by_hex = self.batch_get_chronik_tokens(token_ids).await?; - let json_txs = block_txs_to_json(block, &tokens_by_hex)?; + + let json_txs = block_txs_to_json(block, block_txs, &tokens_by_hex)?; Ok(JsonTxsResponse { data: json_txs }) } pub async fn data_address_txs( &self, address: &str, query: HashMap, ) -> Result { let address = CashAddress::parse_cow(address.into())?; let (script_type, script_payload) = cash_addr_to_script_type_payload(&address); let script_endpoint = self.chronik.script(script_type, &script_payload); let page: usize = query .get("page") .map(|s| s.as_str()) .unwrap_or("0") .parse()?; let take: usize = query .get("take") .map(|s| s.as_str()) .unwrap_or("200") .parse()?; let address_tx_history = script_endpoint.history_with_page_size(page, take).await?; let token_ids = address_tx_history .txs .iter() .filter_map(|tx| { - let slp_tx_data = tx.slp_tx_data.as_ref()?; - let slp_meta = slp_tx_data.slp_meta.as_ref()?; - if slp_meta.token_type() == SlpTokenType::UnknownTokenType { + let token_entry = tx.token_entries.get(0)?; + if Self::is_unknown_slp(&token_entry.token_type).ok()? { return None; } - Some(Sha256d::from_slice_be_or_null(&slp_meta.token_id)) + Some( + Sha256d::from_hex_be(&token_entry.token_id) + .expect("Impossible"), + ) }) .collect(); let tokens = self.batch_get_chronik_tokens(token_ids).await?; let json_tokens = tokens_to_json(&tokens)?; + let json_txs = tx_history_to_json(&address, address_tx_history, &json_tokens)?; Ok(JsonTxsResponse { data: json_txs }) } } impl Server { pub async fn block(&self, block_hex: &str) -> Result { let block_hash = Sha256d::from_hex_be(block_hex)?; let block = self.chronik.block_by_hash(&block_hash).await?; + let block_txs = self + .chronik + .block_txs_by_hash_with_page_size(&block_hash, 0, 1) + .await?; let block_info = block.block_info.ok_or_else(|| eyre!("Block has no info"))?; let blockchain_info = self.chronik.blockchain_info().await?; let best_height = blockchain_info.tip_height; let difficulty = calculate_block_difficulty(block_info.n_bits); let timestamp = Utc.timestamp_nanos(block_info.timestamp * 1_000_000_000); - let coinbase_data = block.txs[0].inputs[0].input_script.clone(); + let coinbase_data = block_txs.txs[0].inputs[0].input_script.clone(); let confirmations = best_height - block_info.height + 1; let block_template = BlockTemplate { block_hex, block_info, confirmations, timestamp, difficulty, coinbase_data, best_height, }; Ok(block_template.render().unwrap()) } pub async fn tx(&self, tx_hex: &str) -> Result { let tx_hash = Sha256d::from_hex_be(tx_hex)?; let tx = self.chronik.tx(&tx_hash).await?; - let (token_id, token) = match &tx.slp_tx_data { - Some(slp_tx_data) => { - let slp_meta = - slp_tx_data.slp_meta.as_ref().expect("Impossible"); - let token_id = Sha256d::from_slice_be(&slp_meta.token_id)?; + let token_entry = tx + .token_entries + .get(0) + .and_then(|entry| Some(entry.clone())); + + let (token_id, token) = match &token_entry { + Some(token_entry) => { + let token_id = Sha256d::from_hex_be(&token_entry.token_id)?; let mut token = None; - if slp_meta.token_type() != SlpTokenType::UnknownTokenType { + let tx_type = TokenTxType::from_i32(token_entry.tx_type) + .ok_or_else(|| eyre!("Malformed token_entry.tx_type"))?; + if tx_type != TokenTxType::Unknown { token = Some(self.chronik.token(&token_id).await?); } (Some(token_id), token) } None => (None, None), }; let token_ticker = token.as_ref().and_then(|token| { Some(String::from_utf8_lossy( - &token - .slp_tx_data - .as_ref()? - .genesis_info - .as_ref()? - .token_ticker, + &token.genesis_info.as_ref()?.token_ticker, )) }); + let (title, is_token): (Cow, bool) = match &token_ticker { Some(token_ticker) => { (format!("{} Transaction", token_ticker).into(), true) } - None => { - if tx.slp_error_msg.is_empty() { - ("eCash Transaction".into(), false) - } else { - ("Invalid eToken Transaction".into(), true) - } - } + None => match &tx.token_failed_parsings.get(0) { + None => ("eCash Transaction".into(), false), + Some(_) => ("Invalid eToken Transaction".into(), true), + }, }; let token_hex = token_id.as_ref().map(|token| token.to_hex_be()); let (token_section_title, action_str, specification): ( Cow, Cow, Cow, - ) = match &tx.slp_tx_data { - Some(slp_tx_data) => { - let slp_meta = - slp_tx_data.slp_meta.as_ref().expect("Impossible"); - let token_type = SlpTokenType::from_i32(slp_meta.token_type) - .ok_or_else(|| eyre!("Malformed slp_meta"))?; - let tx_type = SlpTxType::from_i32(slp_meta.tx_type) - .ok_or_else(|| eyre!("Malformed slp_meta"))?; - - let action_str = match (token_type, tx_type) { - (SlpTokenType::Fungible, SlpTxType::Genesis) => "GENESIS", - (SlpTokenType::Fungible, SlpTxType::Mint) => "MINT", - (SlpTokenType::Fungible, SlpTxType::Send) => "SEND", - (SlpTokenType::Fungible, SlpTxType::Burn) => "BURN", - (SlpTokenType::Nft1Group, SlpTxType::Genesis) => { - "NFT1 GROUP GENESIS" - } - (SlpTokenType::Nft1Group, SlpTxType::Mint) => { - "NFT1 GROUP MINT" - } - (SlpTokenType::Nft1Group, SlpTxType::Send) => { - "NFT1 GROUP SEND" - } - (SlpTokenType::Nft1Group, SlpTxType::Burn) => { - "NFT1 GROUP BURN" - } - (SlpTokenType::Nft1Child, SlpTxType::Genesis) => { - "NFT1 Child GENESIS" - } - (SlpTokenType::Nft1Child, SlpTxType::Send) => { - "NFT1 Child SEND" + ) = match &token_entry { + Some(token_entry) => { + let token_type = token_entry + .token_type + .clone() + .ok_or_else(|| eyre!("Malformed token_entry.token_type"))? + .token_type + .ok_or_else(|| eyre!("Malformed token_entry.token_type"))?; + let tx_type = TokenTxType::from_i32(token_entry.tx_type) + .ok_or_else(|| eyre!("Malformed token_entry.tx_type"))?; + + let action_str = match token_type { + token_type::TokenType::Slp(slp) => { + let slp_token_type = SlpTokenType::from_i32(slp) + .ok_or_else(|| eyre!("Malformed SlpTokenType"))?; + match (slp_token_type, tx_type) { + (SlpTokenType::Fungible, TokenTxType::Genesis) => { + "SLP GENESIS" + } + (SlpTokenType::Fungible, TokenTxType::Mint) => { + "SLP MINT" + } + (SlpTokenType::Fungible, TokenTxType::Send) => { + "SLP SEND" + } + (SlpTokenType::Fungible, TokenTxType::Burn) => { + "SLP BURN" + } + (SlpTokenType::Nft1Group, TokenTxType::Genesis) => { + "NFT1 GROUP GENESIS" + } + (SlpTokenType::Nft1Group, TokenTxType::Mint) => { + "NFT1 GROUP MINT" + } + (SlpTokenType::Nft1Group, TokenTxType::Send) => { + "NFT1 GROUP SEND" + } + (SlpTokenType::Nft1Group, TokenTxType::Burn) => { + "NFT1 GROUP BURN" + } + (SlpTokenType::Nft1Child, TokenTxType::Genesis) => { + "NFT1 Child GENESIS" + } + (SlpTokenType::Nft1Child, TokenTxType::Send) => { + "NFT1 Child SEND" + } + (SlpTokenType::Nft1Child, TokenTxType::Burn) => { + "NFT1 Child BURN" + } + (SlpTokenType::MintVault, TokenTxType::Genesis) => { + "SLPv2 GENESIS" + } + (SlpTokenType::MintVault, TokenTxType::Mint) => { + "SLPv2 MINT" + } + (SlpTokenType::MintVault, TokenTxType::Send) => { + "SLPv2 SEND" + } + (SlpTokenType::MintVault, TokenTxType::Burn) => { + "SLPv2 BURN" + } + _ => "SLP Unknown", + } } - (SlpTokenType::Nft1Child, SlpTxType::Burn) => { - "NFT1 Child BURN" + token_type::TokenType::Alp(alp) => { + let alp_token_type = AlpTokenType::from_i32(alp) + .ok_or_else(|| eyre!("Malformed AlpTokenType"))?; + match (alp_token_type, tx_type) { + (AlpTokenType::Standard, TokenTxType::Genesis) => { + "ALP GENESIS" + } + (AlpTokenType::Standard, TokenTxType::Mint) => { + "ALP MINT" + } + (AlpTokenType::Standard, TokenTxType::Send) => { + "ALP SEND" + } + (AlpTokenType::Standard, TokenTxType::Burn) => { + "ALP BURN" + } + _ => "ALP Unknown", + } } - _ => "Unknown", }; let specification = match token_type { - SlpTokenType::Fungible => { - "https://github.com/simpleledger/\ - slp-specifications/blob/master/\ - slp-token-type-1.md" + token_type::TokenType::Slp(slp) => { + let slp_token_type = SlpTokenType::from_i32(slp) + .ok_or_else(|| eyre!("Malformed SlpTokenType"))?; + match slp_token_type { + SlpTokenType::Fungible => { + "https://github.com/simpleledger/\ + slp-specifications/blob/master/\ + slp-token-type-1.md" + } + SlpTokenType::MintVault => { + "https://github.com/badger-cash/\ + slp-specifications/blob/master/\ + slp-token-type-2.md" + } + SlpTokenType::Nft1Group + | SlpTokenType::Nft1Child => { + "https://github.com/simpleledger/\ + slp-specifications/blob/master/slp-nft-1.md" + } + _ => "Unknown", + } } - SlpTokenType::Nft1Group - | SlpTokenType::Nft1Child => { - "https://github.com/simpleledger/\ - slp-specifications/blob/master/slp-nft-1.md" + token_type::TokenType::Alp(_) => { + "https://ecashbuilders.notion.site/\ + ALP-a862a4130877448387373b9e6a93dd97" } - _ => "Unknown", }; ( - format!("Token Details ({} Transaction)", action_str) + format!("Token Details ({} Transaction)", &action_str) .into(), action_str.into(), specification.into(), ) } None => { - if tx.slp_error_msg.is_empty() { + if tx.token_failed_parsings.get(0).is_some() { ( "Token Details (Invalid Transaction)".into(), "Unknown".into(), "Unknown".into(), ) } else { ("".into(), "Unknown".into(), "Unknown".into()) } } }; let blockchain_info = self.chronik.blockchain_info().await?; let confirmations = match &tx.block { Some(block_meta) => { blockchain_info.tip_height - block_meta.height + 1 } None => 0, }; let timestamp = match &tx.block { Some(block_meta) => block_meta.timestamp, None => tx.time_first_seen, }; let timestamp = Utc.timestamp_nanos(timestamp * 1_000_000_000); let raw_tx = self.chronik.raw_tx(&tx_hash).await?; let raw_tx = raw_tx.hex(); let tx_stats = calc_tx_stats(&tx, None); let transaction_template = TransactionTemplate { title: &title, sats_addr_prefix: &self.satoshi_addr_prefix, tokens_addr_prefix: &self.tokens_addr_prefix, token_section_title: &token_section_title, is_token, tx_hex, token_hex, - slp_meta: tx - .slp_tx_data - .as_ref() - .and_then(|slp_tx_data| slp_tx_data.slp_meta.clone()), tx, - slp_genesis_info: token - .and_then(|token| token.slp_tx_data?.genesis_info), + slp_genesis_info: token.and_then(|token| token.genesis_info), + slp_meta: token_entry, sats_input: tx_stats.sats_input, sats_output: tx_stats.sats_output, token_input: tx_stats.token_input, token_output: tx_stats.token_output, raw_tx, confirmations, timestamp, action_str: &action_str, specification: &specification, }; Ok(transaction_template.render().unwrap()) } } impl Server { pub async fn address<'a>(&'a self, address: &str) -> Result { let address = CashAddress::parse_cow(address.into())?; let sats_address = address.with_prefix(self.satoshi_addr_prefix); let token_address = address.with_prefix(self.tokens_addr_prefix); let legacy_address = to_legacy_address(&address); let sats_address = sats_address.as_str(); let token_address = token_address.as_str(); let (script_type, script_payload) = cash_addr_to_script_type_payload(&address); let script_endpoint = self.chronik.script(script_type, &script_payload); let page_size = 1; let address_tx_history = script_endpoint.history_with_page_size(0, page_size).await?; let address_num_txs = address_tx_history.num_pages; let utxos = script_endpoint.utxos().await?; let mut token_dust: i64 = 0; let mut total_xec: i64 = 0; let mut token_ids: HashSet = HashSet::new(); - let mut token_utxos: Vec = Vec::new(); + let mut token_utxos: Vec = Vec::new(); let mut json_balances: HashMap = HashMap::new(); let mut main_json_balance: JsonBalance = JsonBalance { token_id: None, sats_amount: 0, token_amount: 0, utxos: Vec::new(), }; - for utxo_script in utxos.into_iter() { - for utxo in utxo_script.utxos.into_iter() { - let OutPoint { txid, out_idx } = - &utxo.outpoint.as_ref().unwrap(); - let mut json_utxo = JsonUtxo { - tx_hash: to_be_hex(txid), - out_idx: *out_idx, - sats_amount: utxo.value, - token_amount: 0, - is_coinbase: utxo.is_coinbase, - block_height: utxo.block_height, - }; - - match (&utxo.slp_meta, &utxo.slp_token) { - (Some(slp_meta), Some(slp_token)) => { - let token_id_hex = hex::encode(&slp_meta.token_id); - let token_id_hash = - Sha256d::from_slice_be_or_null(&slp_meta.token_id); - - json_utxo.token_amount = slp_token.amount; - - match json_balances.entry(token_id_hex) { - Entry::Occupied(mut entry) => { - let entry = entry.get_mut(); - entry.sats_amount += utxo.value; - entry.token_amount += - i128::from(slp_token.amount); - entry.utxos.push(json_utxo); - } - Entry::Vacant(entry) => { - entry.insert(JsonBalance { - token_id: Some(hex::encode( - &slp_meta.token_id, - )), - sats_amount: utxo.value, - token_amount: slp_token.amount.into(), - utxos: vec![json_utxo], - }); - } + for utxo in utxos.into_iter() { + let OutPoint { txid, out_idx } = &utxo.outpoint.as_ref().unwrap(); + let mut json_utxo = JsonUtxo { + tx_hash: to_be_hex(txid), + out_idx: *out_idx, + sats_amount: utxo.value, + token_amount: 0, + is_coinbase: utxo.is_coinbase, + block_height: utxo.block_height, + }; + + match &utxo.token { + Some(token) => { + let token_id_hex = hex::encode(&token.token_id); + let token_id_hash = Sha256d::from_slice_be_or_null( + &token.token_id.as_bytes(), + ); + + json_utxo.token_amount = token.amount; + + match json_balances.entry(token_id_hex) { + Entry::Occupied(mut entry) => { + let entry = entry.get_mut(); + entry.sats_amount += utxo.value; + entry.token_amount += i128::from(token.amount); + entry.utxos.push(json_utxo); + } + Entry::Vacant(entry) => { + entry.insert(JsonBalance { + token_id: Some(hex::encode(&token.token_id)), + sats_amount: utxo.value, + token_amount: token.amount.into(), + utxos: vec![json_utxo], + }); } - - token_ids.insert(token_id_hash); - token_dust += utxo.value; - token_utxos.push(utxo); - } - _ => { - total_xec += utxo.value; - main_json_balance.utxos.push(json_utxo); } - }; - } + + token_ids.insert(token_id_hash); + token_dust += utxo.value; + token_utxos.push(utxo); + } + _ => { + total_xec += utxo.value; + main_json_balance.utxos.push(json_utxo); + } + }; } json_balances.insert(String::from("main"), main_json_balance); let tokens = self.batch_get_chronik_tokens(token_ids).await?; let json_tokens = tokens_to_json(&tokens)?; let encoded_tokens = serde_json::to_string(&json_tokens)?.replace('\'', r"\'"); let encoded_balances = serde_json::to_string(&json_balances)?.replace('\'', r"\'"); let address_template = AddressTemplate { tokens, token_utxos, token_dust, total_xec, address_num_txs, address: address.as_str(), sats_address, token_address, legacy_address, json_balances, encoded_tokens, encoded_balances, }; Ok(address_template.render().unwrap()) } pub async fn batch_get_chronik_tokens( &self, token_ids: HashSet, - ) -> Result> { + ) -> Result> { let mut token_calls = Vec::new(); let mut token_map = HashMap::new(); + let unknown_token = Sha256d::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + )?; + for token_id in token_ids.iter() { - token_calls.push(Box::pin(self.chronik.token(token_id))); + if token_id != &unknown_token { + token_calls.push(Box::pin(self.chronik.token(token_id))); + } } let tokens = future::try_join_all(token_calls).await?; for token in tokens.into_iter() { - if let Some(slp_tx_data) = &token.slp_tx_data { - if let Some(slp_meta) = &slp_tx_data.slp_meta { - token_map.insert(hex::encode(&slp_meta.token_id), token); - } - } + token_map.insert(hex::encode(&token.token_id), token); } Ok(token_map) } pub async fn address_qr(&self, address: &str) -> Result> { use qrcode_generator::QrCodeEcc; if address.len() > 60 { bail!("Invalid address length"); } let png = qrcode_generator::to_png_to_vec(address, QrCodeEcc::Quartile, 140)?; Ok(png) } pub async fn block_height(&self, height: u32) -> Result { let block = self.chronik.block_by_height(height as i32).await.ok(); match block { Some(block) => { let block_info = block.block_info.expect("Impossible"); Ok(self.redirect(format!( "/block/{}", to_be_hex(&block_info.hash) ))) } None => Ok(self.redirect("/404".into())), } } pub async fn search(&self, query: &str) -> Result { if let Ok(address) = CashAddress::parse_cow(query.into()) { return Ok(self.redirect(format!("/address/{}", address.as_str()))); } // Check for prefixless address search if let Ok(address) = format!("{}:{}", self.satoshi_addr_prefix, query) .parse::() { return Ok(self.redirect(format!("/address/{}", address.as_str()))); } if let Ok(address) = format!("{}:{}", self.tokens_addr_prefix, query) .parse::() { return Ok(self.redirect(format!("/address/{}", address.as_str()))); } if let Ok(height) = query.parse::() { if self.chronik.block_by_height(height).await.is_ok() { return Ok(self.redirect(format!("/block-height/{}", query))); } } let bytes = from_be_hex(query)?; let unknown_hash = Sha256d::from_slice(&bytes)?; if self.chronik.tx(&unknown_hash).await.is_ok() { return Ok(self.redirect(format!("/tx/{}", query))); } if self.chronik.block_by_hash(&unknown_hash).await.is_ok() { return Ok(self.redirect(format!("/block/{}", query))); } Ok(self.redirect("/404".into())) } pub fn redirect(&self, url: String) -> Redirect { Redirect::permanent(&url) } } diff --git a/web/explorer/explorer-server/src/server_http.rs b/web/explorer/explorer-server/src/server_http.rs index 0c18b5749..8672eb8db 100644 --- a/web/explorer/explorer-server/src/server_http.rs +++ b/web/explorer/explorer-server/src/server_http.rs @@ -1,108 +1,108 @@ use std::{collections::HashMap, sync::Arc}; use axum::{ extract::{Path, Query}, http::StatusCode, response::{Html, IntoResponse, Redirect}, routing::{get_service, MethodRouter}, Extension, Json, }; use futures::future::ready; use tower_http::services::ServeDir; use crate::{ server::Server, server_error::{to_server_error, ServerError}, server_primitives::{JsonBlocksResponse, JsonTxsResponse}, }; pub async fn blocks( server: Extension>, ) -> Result, ServerError> { Ok(Html(server.blocks().await.map_err(to_server_error)?)) } pub async fn tx( Path(hash): Path, server: Extension>, ) -> Result, ServerError> { Ok(Html(server.tx(&hash).await.map_err(to_server_error)?)) } pub async fn block( Path(hash): Path, server: Extension>, ) -> Result, ServerError> { Ok(Html(server.block(&hash).await.map_err(to_server_error)?)) } pub async fn address( Path(hash): Path, server: Extension>, ) -> Result, ServerError> { Ok(Html(server.address(&hash).await.map_err(to_server_error)?)) } pub async fn address_qr( Path(hash): Path, server: Extension>, ) -> Result { let qr_code = server.address_qr(&hash).await.map_err(to_server_error)?; Ok((StatusCode::OK, [("content-type", "image/png")], qr_code)) } pub async fn block_height( Path(height): Path, server: Extension>, ) -> Result { Ok(server.block_height(height).await.map_err(to_server_error)?) } pub async fn search( Path(query): Path, server: Extension>, ) -> Result { server.search(&query).await.map_err(to_server_error) } pub async fn data_blocks( Path((start_height, end_height)): Path<(i32, i32)>, server: Extension>, ) -> Result, ServerError> { Ok(Json( server .data_blocks(start_height, end_height) .await .map_err(to_server_error)?, )) } pub async fn data_block_txs( - Path(hash): Path, + Path((hash, page, page_size)): Path<(String, usize, usize)>, server: Extension>, ) -> Result, ServerError> { Ok(Json( server - .data_block_txs(&hash) + .data_block_txs(&hash, page, page_size) .await .map_err(to_server_error)?, )) } pub async fn data_address_txs( Path(hash): Path, Query(query): Query>, server: Extension>, ) -> Result, ServerError> { Ok(Json( server .data_address_txs(&hash, query) .await .map_err(to_server_error)?, )) } pub fn serve_files(path: &std::path::Path) -> MethodRouter { get_service(ServeDir::new(path)) .handle_error(|_| ready(StatusCode::INTERNAL_SERVER_ERROR)) } diff --git a/web/explorer/explorer-server/src/templating.rs b/web/explorer/explorer-server/src/templating.rs index 5a1794811..e1e9f6e30 100644 --- a/web/explorer/explorer-server/src/templating.rs +++ b/web/explorer/explorer-server/src/templating.rs @@ -1,76 +1,76 @@ use std::collections::HashMap; use askama::Template; use bitcoinsuite_chronik_client::proto::{ - BlockInfo, SlpGenesisInfo, SlpMeta, Token, Tx, Utxo, + BlockInfo, GenesisInfo, ScriptUtxo, TokenEntry, TokenInfo, Tx, }; use chrono::{DateTime, Utc}; use crate::{blockchain::Destination, server_primitives::JsonBalance}; mod filters; #[derive(Template)] #[template(path = "pages/blocks.html")] pub struct BlocksTemplate { pub last_block_height: u32, } #[derive(Template)] #[template(path = "pages/block.html")] pub struct BlockTemplate<'a> { pub block_hex: &'a str, pub block_info: BlockInfo, pub confirmations: i32, pub timestamp: DateTime, pub difficulty: f64, pub coinbase_data: Vec, pub best_height: i32, } #[derive(Template)] #[template(path = "pages/transaction.html")] pub struct TransactionTemplate<'a> { pub title: &'a str, pub sats_addr_prefix: &'a str, pub tokens_addr_prefix: &'a str, pub token_section_title: &'a str, pub is_token: bool, pub tx_hex: &'a str, pub token_hex: Option, pub tx: Tx, - pub slp_genesis_info: Option, - pub slp_meta: Option, + pub slp_genesis_info: Option, + pub slp_meta: Option, pub raw_tx: String, pub confirmations: i32, pub timestamp: DateTime, pub sats_input: i64, pub sats_output: i64, pub token_input: i128, pub token_output: i128, pub action_str: &'a str, pub specification: &'a str, } #[derive(Template)] #[template(path = "pages/address.html")] pub struct AddressTemplate<'a> { - pub tokens: HashMap, + pub tokens: HashMap, pub token_dust: i64, pub total_xec: i64, - pub token_utxos: Vec, + pub token_utxos: Vec, pub address_num_txs: u32, pub address: &'a str, pub sats_address: &'a str, pub token_address: &'a str, pub legacy_address: String, pub json_balances: HashMap, pub encoded_tokens: String, pub encoded_balances: String, } #[derive(Template)] #[template(path = "pages/error.html")] pub struct ErrorTemplate { pub message: String, } diff --git a/web/explorer/explorer-server/src/templating/filters.rs b/web/explorer/explorer-server/src/templating/filters.rs index 52ee9827a..e95644a59 100644 --- a/web/explorer/explorer-server/src/templating/filters.rs +++ b/web/explorer/explorer-server/src/templating/filters.rs @@ -1,218 +1,218 @@ use std::collections::HashMap; -use bitcoinsuite_chronik_client::proto::{OutPoint, SlpToken, Token}; +use bitcoinsuite_chronik_client::proto::{OutPoint, Token, TokenInfo}; use bitcoinsuite_core::Script; use chrono::DateTime; use chrono_humanize::HumanTime; use humansize::{file_size_opts as options, FileSize}; use maud::{html, PreEscaped}; use num_format::{Locale, ToFormattedString}; use crate::blockchain; fn render_integer_with_small_flag( int: i128, smallify: bool, ) -> askama::Result { let string = int.to_formatted_string(&Locale::en); let parts = string.split(',').collect::>(); let output = html! { @for (idx, part) in parts.iter().enumerate() { @if idx >= 2 && smallify { small.digit-sep[idx < parts.len() - 1] { (part) } } @else { span.digit-sep[idx < parts.len() - 1] { (part) } } } }; Ok(output.into_string()) } pub fn max(value: &i64, maximum: &i64) -> askama::Result { Ok(*value.max(maximum)) } pub fn check_is_coinbase(outpoint: &OutPoint) -> askama::Result { Ok(outpoint.txid == [0; 32] && outpoint.out_idx == 0xffff_ffff) } pub fn destination_from_script<'a>( script: &'a [u8], is_token: &bool, sats_addr_prefix: &'a str, tokens_addr_prefix: &'a str, ) -> askama::Result> { let prefix = if *is_token { tokens_addr_prefix } else { sats_addr_prefix }; Ok(blockchain::destination_from_script(prefix, script)) } pub fn get_script(signature_script: &[u8]) -> askama::Result { let script = Script::from_slice(signature_script); Ok(script.to_string()) } -pub fn check_is_token(slp_token: &Option) -> askama::Result { - Ok(slp_token +pub fn check_is_token(token: &Option) -> askama::Result { + Ok(token .as_ref() .map(|slp| slp.amount > 0 || slp.is_mint_baton) .unwrap_or(false)) } pub fn human_time( timestamp: &DateTime, ) -> askama::Result { Ok(HumanTime::from(*timestamp)) } pub fn render_integer(int: &i128) -> askama::Result { render_integer_with_small_flag(*int, false) } pub fn render_integer_smallify(int: &i128) -> askama::Result { render_integer_with_small_flag(*int, true) } pub fn render_human_size(value: &u64) -> askama::Result { Ok(value.file_size(options::CONVENTIONAL).unwrap()) } pub fn render_difficulty(difficulty: &f64) -> askama::Result { let est_hashrate = difficulty * (0xffffffffu64 as f64) / 600.0; let hashrate = if est_hashrate < 1e12 { html! { (format!("{:.2} GH/s", est_hashrate / 1e9)) } } else if est_hashrate < 1e15 { html! { (format!("{:.2} TH/s", est_hashrate / 1e12)) } } else if est_hashrate < 1e18 { html! { (format!("{:.2} PH/s", est_hashrate / 1e15)) } } else { html! { (format!("{:.2} EH/s", est_hashrate / 1e18)) } }; let num_digits = difficulty.log10().floor(); let exponent = (num_digits / 3.0) as u32; let difficulty = match exponent { 0 => html! { (format!("{:.0}", difficulty)) }, 1 => html! { (format!("{:.2}", difficulty / 1e3)) " ×10" sup { "3" } }, 2 => html! { (format!("{:.2}", difficulty / 1e6)) " ×10" sup { "6" } }, 3 => html! { (format!("{:.2}", difficulty / 1e9)) " ×10" sup { "9" } }, 4 => { html! { (format!("{:.2}", difficulty / 1e12)) " ×10" sup { "12" } } } _ => { html! { (format!("{:.2}", difficulty / 1e15)) " ×10" sup { "15" } } } }; let output = html! { (difficulty) small { " (10 min. blocks = " (hashrate) ")" } }; Ok(output.into_string()) } pub fn render_integer_with_commas(int: &u64) -> askama::Result { let string = int.to_formatted_string(&Locale::en); let parts = string.split(',').collect::>(); let output = html! { @for (idx, part) in parts.iter().enumerate() { @if idx != 0 { span.non-selectable { "," } } span { (part) } } }; Ok(output.into_string()) } pub fn render_sats(sats: &i64) -> askama::Result { let coins = *sats as f64 / 100.0; let fmt = format!("{:.2}", coins); let mut parts = fmt.split('.'); let integer_part: u64 = parts.next().unwrap().parse().unwrap(); let fract_part = parts.next().unwrap(); let output = { let output = html! { (PreEscaped(render_integer_with_commas(&integer_part)?)) "." small { (fract_part) } }; output.into_string() }; Ok(output) } pub fn hexify_u8_vector(value: &[u8]) -> askama::Result { Ok(hex::encode(value)) } pub fn string_from_lossy_utf8(value: &[u8]) -> askama::Result { Ok(String::from_utf8_lossy(value).to_string()) } pub fn to_le_hex(slice: &[u8]) -> askama::Result { Ok(blockchain::to_be_hex(slice)) } pub fn u32_to_u64(value: &u32) -> askama::Result { Ok(*value as u64) } pub fn to_i128 + Copy>(value: &T) -> askama::Result { Ok((*value).into()) } pub fn render_token_amount( base_amount: &i128, decimals: &u32, ) -> askama::Result { let decimals = *decimals as usize; if decimals == 0 { return render_integer(base_amount); } let base_amount_str = format!("{:0digits$}", base_amount, digits = decimals + 1); let decimal_idx = base_amount_str.len() - decimals; let integer_part: i128 = base_amount_str[..decimal_idx].parse().unwrap(); let fract_part = &base_amount_str[decimal_idx..]; let num_fract_sections = (decimals as usize + 2) / 3; let mut all_zeros = true; let mut rendered = html! {}; for section_idx in (0..num_fract_sections).rev() { let offset = section_idx * 3; let section = &fract_part[offset..fract_part.len().min(offset + 3)]; if !section.chars().all(|c| c == '0') { all_zeros = false; } rendered = html! { small.zeros[all_zeros].digit-sep[ section_idx != num_fract_sections - 1] { (section) } (rendered) }; } let output = html! { (PreEscaped(render_integer(&integer_part)?)) "." (rendered) }; Ok(output.into_string()) } pub fn get_token<'a>( - tokens: &'a HashMap, + tokens: &'a HashMap, token_id: &str, -) -> askama::Result> { +) -> askama::Result> { Ok(tokens.get(token_id)) } diff --git a/web/explorer/explorer-server/templates/components/input.html b/web/explorer/explorer-server/templates/components/input.html index 5a2b652ec..90bbaa3f0 100644 --- a/web/explorer/explorer-server/templates/components/input.html +++ b/web/explorer/explorer-server/templates/components/input.html @@ -1,66 +1,65 @@ {% macro render(index, input, tx, slp_genesis_info, sats_addr_prefix, -tokens_addr_prefix) %} {% let is_token = input.slp_token|check_is_token %} {% -let destination = input.output_script|destination_from_script(is_token, +tokens_addr_prefix) %} {% let is_token = input.token|check_is_token %} {% let +destination = input.output_script|destination_from_script(is_token, sats_addr_prefix, tokens_addr_prefix) %} {% let decoded_input_script = input.input_script|get_script %}
{% match input.prev_out %} {% when Some with (prev_out) %} {% if prev_out|check_is_coinbase %}
Coinbase
{% else %}
{{ index }}
{% match destination %} {% when Destination::Address with (address) %} {{ address.as_str() }} {% when Destination::P2PK with (pubkey) %} Pubkey: {{ pubkey|hexify_u8_vector }} {% when Destination::Unknown with (_bytes) %} Unknown {% when Destination::Nulldata with (_ops) %} Unreachable {% endmatch %}
- {% match input.slp_token %} {% when Some with (slp_token) %} {% - match tx.slp_tx_data %} {% when Some with (slp_tx_data) %} {% + {% match input.token %} {% when Some with (slp_token) %} {% match slp_genesis_info %} {% when Some with (genesis_info) %} {% if slp_token.amount > 0 || slp_token.is_mint_baton %} {% if slp_token.is_mint_baton %}
Mint baton
{% else %} {{ slp_token.amount|to_i128|render_token_amount(genesis_info.decimals)|safe }} {{ genesis_info.token_ticker|string_from_lossy_utf8 }} {% endif %} {% endif %}
{{ input.value|render_sats|safe }} XEC
{% when None %} {{ input.value|render_sats|safe }} XEC {% when - None %} {% endmatch %} {% when None %} {% endmatch %} {% when - None %} {{ input.value|render_sats|safe }} XEC {% endmatch %} + None %} {% endmatch %} {% when None %} {{ + input.value|render_sats|safe }} XEC {% endmatch %}
{% endif %} {% when None %} {% endmatch %}
{% endmacro %} diff --git a/web/explorer/explorer-server/templates/components/output.html b/web/explorer/explorer-server/templates/components/output.html index e6d6b6210..c143830b4 100644 --- a/web/explorer/explorer-server/templates/components/output.html +++ b/web/explorer/explorer-server/templates/components/output.html @@ -1,65 +1,64 @@ {% macro render(index, output, tx, slp_genesis_info, sats_addr_prefix, -tokens_addr_prefix) %} {% let is_token = output.slp_token|check_is_token %} {% -let destination = output.output_script|destination_from_script(is_token, +tokens_addr_prefix) %} {% let is_token = output.token|check_is_token %} {% let +destination = output.output_script|destination_from_script(is_token, sats_addr_prefix, tokens_addr_prefix) %} {% let decoded_output_script = output.output_script|get_script %}
{% match destination %} {% when Destination::Address with (address) %} {% when Destination::Nulldata with (_ops) %} OP_RETURN data {% when Destination::P2PK with (pubkey) %} Pubkey: {{ pubkey|hexify_u8_vector }}, {% when Destination::Unknown with (_bytes) %} Unknown {% endmatch %}
- {% match output.slp_token %} {% when Some with (slp_token) %} {% - match tx.slp_tx_data %} {% when Some with (slp_tx_data) %} {% + {% match output.token %} {% when Some with (slp_token) %} {% match slp_genesis_info %} {% when Some with (genesis_info) %} {% if slp_token.amount > 0 || slp_token.is_mint_baton %} {% if slp_token.is_mint_baton %}
Mint baton
{% else %} {{ slp_token.amount|to_i128|render_token_amount(genesis_info.decimals)|safe }} {{ genesis_info.token_ticker|string_from_lossy_utf8 }} {% endif %} {% endif %}
{{ output.value|render_sats|safe }} XEC
{% when None %} {{ output.value|render_sats|safe }} XEC {% - endmatch %} {% when None %} {% endmatch %} {% when None %} {{ - output.value|render_sats|safe }} XEC {% endmatch %} + endmatch %} {% when None %} {{ output.value|render_sats|safe }} + XEC {% endmatch %}
{{ index }}
{% match output.spent_by %} {% when Some with (outpoint) %} {% when None %} {% endmatch %}
{% endmacro %} diff --git a/web/explorer/explorer-server/templates/components/token_info_table.html b/web/explorer/explorer-server/templates/components/token_info_table.html index 609d207c1..73d8307ee 100644 --- a/web/explorer/explorer-server/templates/components/token_info_table.html +++ b/web/explorer/explorer-server/templates/components/token_info_table.html @@ -1,81 +1,79 @@ -{% macro render(tx, slp_genesis_info, slp_meta, token_input, token_output) %} {% -match slp_genesis_info %} {% when Some with (genesis_info) %} +{% macro render(tx, slp_genesis_info, slp_meta, token_input, token_output, +action_str, specification) %} {% match slp_genesis_info %} {% when Some with +(genesis_info) %}
Token Ticker
{{ genesis_info.token_ticker|string_from_lossy_utf8 }}
Token Name
{{ genesis_info.token_name|string_from_lossy_utf8 }}
Token Type
{{ specification }}
Transaction Type
{{ action_str }}
Token Output
{{ token_output|render_token_amount(genesis_info.decimals)|safe }} {{ genesis_info.token_ticker|string_from_lossy_utf8 }} {% if token_output < token_input %}
({{ (token_input - token_output)|render_token_amount(genesis_info.decimals)|safe }} {{ genesis_info.token_ticker|string_from_lossy_utf8 }} burned) {% endif %}
Document URI
- {% let token_url = - genesis_info.token_document_url|string_from_lossy_utf8 %} + {% let token_url = genesis_info.url|string_from_lossy_utf8 %} {{ token_url }}
Document Hash
- {% match genesis_info.token_document_url.len() %} {% when 0 %} + {% match genesis_info.url.len() %} {% when 0 %}
Not set
{% when _ %} -
- {{ genesis_info.token_document_hash|hexify_u8_vector }} -
+
{{ genesis_info.hash|hexify_u8_vector }}
{% endmatch %}
Decimals
{{ genesis_info.decimals }}
{% when None %} {% endmatch %} {% endmacro %} diff --git a/web/explorer/explorer-server/templates/pages/address.html b/web/explorer/explorer-server/templates/pages/address.html index 1728ced07..3187a193d 100644 --- a/web/explorer/explorer-server/templates/pages/address.html +++ b/web/explorer/explorer-server/templates/pages/address.html @@ -1,221 +1,220 @@ {% extends "base.html" %} {% block footer_classes %}hidden{% endblock %} {% block content %}

Address

{% if sats_address == address %}

{{ sats_address }}

{% else %}

{{ token_address }}

{% endif %}
Copy to clipboard

Balance

{{ total_xec|render_sats|safe }} XEC

{% if token_dust > 0 %}

+{{ token_dust|render_sats|safe }} XEC in token dust

{% endif %}

Transactions

{{ address_num_txs }}

{% if sats_address == address %}
{% if total_xec > 0 %} Coins {% else %}
Address is empty
{% endif %} {% if token_dust > 0 %}
eTokens {% endif %}
{% endblock %} diff --git a/web/explorer/explorer-server/templates/pages/transaction.html b/web/explorer/explorer-server/templates/pages/transaction.html index 26dfe7a90..5a50d0de3 100644 --- a/web/explorer/explorer-server/templates/pages/transaction.html +++ b/web/explorer/explorer-server/templates/pages/transaction.html @@ -1,317 +1,317 @@ {% extends "base.html" %} {% import "components/input.html" as input %} {% import "components/output.html" as output %} {% import "components/token_info_table.html" as token_info_table %} {% block body_classes %}overflow-y-scroll{% endblock %} {% block content %}

{{ title }}

{% if tx.is_coinbase %}
Coinbase
{% endif %}
Advanced
{% if is_token %} {% else %} {% endif %}
Transaction ID {{ tx_hex }}
Copy to clipboard
Token ID {% match token_hex %} {% when Some with (token_hex) %} {{ token_hex }}
Copy to clipboard
{% when None %} {% endmatch %}
Transaction ID {{ tx_hex }}
Copy to clipboard

General Details

Age
{{ timestamp|human_time }}
Block
{% match tx.block %} {% when Some with (block_meta) %} {{ block_meta.height|to_i128|render_integer|safe }} ({{ confirmations|to_i128|render_integer|safe }} confirmation{% if confirmations|to_i128 > 1 %}s{% endif %}) {% when None %} Not mined yet {% endmatch %}
Unix Timestamp
{% match tx.block %} {% when Some with (block_meta) %} {{ block_meta.timestamp|to_i128|render_integer|safe }} {% when None %} Not mined yet {% endmatch %}
Size
{{ tx.size|u32_to_u64|render_human_size }} ({{ tx.size|to_i128|render_integer_smallify|safe }} B)
Mined On
{% match tx.block %} {% when Some with (block_meta) %}
{% when None %}
Not mined yet
{% endmatch %}
Total Input
{{ sats_input|render_sats|safe }} XEC
Total Output
{{ sats_output|render_sats|safe }} XEC
Fee
{{ (sats_input - sats_output)|max(0)|render_sats|safe }} XEC
{% if is_token %}

{{ token_section_title }}

{% call token_info_table::render(tx, slp_genesis_info, slp_meta, - token_input, token_output) %} + token_input, token_output, action_str, specification) %}
{% endif %}

Transaction

Inputs ({{ tx.inputs.len() }})

{{ timestamp }}
Pre-XEC
(Nov 15, 2020)
Over Five
Years Old
Pre-BCH
(Aug 8, 2017)
{% for input in tx.inputs %} {% call input::render(loop.index0, input, tx, slp_genesis_info, sats_addr_prefix, tokens_addr_prefix) %} {% endfor %}

Outputs ({{ tx.outputs.len() }})

{% for output in tx.outputs %} {% call output::render(loop.index0, output, tx, slp_genesis_info, sats_addr_prefix, tokens_addr_prefix) %} {% endfor %}
{% endblock %}