diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b591cfa --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea +replay.log +.vscode +.DS_Store diff --git a/bitcoin-explorer/.gitignore b/bitcoin-explorer/.gitignore new file mode 100644 index 0000000..2d7bb16 --- /dev/null +++ b/bitcoin-explorer/.gitignore @@ -0,0 +1,6 @@ +.vscode +.idea +.DS_Store +buf.gen.yaml +/target +*.spkg \ No newline at end of file diff --git a/bitcoin-explorer/.gitpod.yml b/bitcoin-explorer/.gitpod.yml new file mode 100644 index 0000000..000c433 --- /dev/null +++ b/bitcoin-explorer/.gitpod.yml @@ -0,0 +1,10 @@ +image: ghcr.io/graphprotocol/substreams-gitpod:latest +tasks: + - command: | + # Authenticate with the substreams server + export SUBSTREAMS_API_TOKEN=$(curl https://auth.dfuse.io/v1/auth/issue -s --data-binary '{"api_key":"'$STREAMINGFAST_KEY'"}' | jq -r .token) +ports: + - port: 6060 + onOpen: ignore + - port: 1065 + onOpen: ignore diff --git a/bitcoin-explorer/.rustfmt.toml b/bitcoin-explorer/.rustfmt.toml new file mode 100644 index 0000000..866c756 --- /dev/null +++ b/bitcoin-explorer/.rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 \ No newline at end of file diff --git a/bitcoin-explorer/Cargo.lock b/bitcoin-explorer/Cargo.lock new file mode 100644 index 0000000..3dcf109 --- /dev/null +++ b/bitcoin-explorer/Cargo.lock @@ -0,0 +1,580 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bigdecimal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[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 = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "pad" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[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-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +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 = "quote" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "substreams" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af972e374502cdfc9998132f5343848d1c58f27a295dc061a89804371f408a46" +dependencies = [ + "anyhow", + "bigdecimal", + "hex", + "hex-literal", + "num-bigint", + "num-traits", + "pad", + "prost", + "prost-build", + "prost-types", + "substreams-macro", + "thiserror", +] + +[[package]] +name = "substreams-bitcoin" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acc68d5ca6a56cc98f673395392638495a58b05f4f3da85e62c095c6090c214" +dependencies = [ + "num-bigint", + "substreams", + "substreams-bitcoin-core", +] + +[[package]] +name = "substreams-bitcoin-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b298c5ce6d4afbcefa00f654df09b4bf2793336b412d4a4caed1eb0a1b926187" +dependencies = [ + "prost", + "prost-build", + "prost-types", + "substreams", +] + +[[package]] +name = "substreams-bitcoin-explorer" +version = "0.1.0" +dependencies = [ + "anyhow", + "prost", + "substreams", + "substreams-bitcoin", +] + +[[package]] +name = "substreams-macro" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6521ccd011a4c3f52cd3c31fc7400733e4feba2094e0e0e6354adca25b2b3f37" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/bitcoin-explorer/Cargo.toml b/bitcoin-explorer/Cargo.toml new file mode 100644 index 0000000..a688d09 --- /dev/null +++ b/bitcoin-explorer/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "substreams-bitcoin-explorer" +version = "0.1.0" +description = "Substreams showcasing the building blocks of Bitcoin" +edition = "2021" +repository = "https://github.com/streamingfast/substreams-explorers" +license = "Apache 2.0" + +[lib] +name = "substreams" +crate-type = ["cdylib"] + +[dependencies] +prost = "0.11" +# Use latest from https://crates.io/crates/substreams +substreams = "0.5" +substreams-bitcoin = { version = "1.0.0" } +anyhow = "1.0" + + +[profile.release] +lto = true +opt-level = 's' +strip = "debuginfo" diff --git a/bitcoin-explorer/Makefile b/bitcoin-explorer/Makefile new file mode 100644 index 0000000..748f21d --- /dev/null +++ b/bitcoin-explorer/Makefile @@ -0,0 +1,11 @@ +.PHONY: protogen +protogen: + substreams protogen ./substreams.yaml --exclude-paths="sf/substreams,google,sf/bitcoin" + +.PHONY: build +build: + cargo build --target wasm32-unknown-unknown --release + +.PHONY: package +package: build + substreams pack substreams.yaml diff --git a/bitcoin-explorer/README.md b/bitcoin-explorer/README.md new file mode 100644 index 0000000..d57c403 --- /dev/null +++ b/bitcoin-explorer/README.md @@ -0,0 +1,66 @@ +# Bitcoin Explorer + +The Bitcoin Explorer consists of several Substreams modules showcasing the most basic operations that you can perform with Substreams on the Bitcoin blockchain. + +## Before You Begin + +Make sure you have the [Substreams CLI installed](https://substreams.streamingfast.io/getting-started/installing-the-cli), and you know the [basic structure of a Substreams module](https://substreams.streamingfast.io/getting-started/quickstart). You must also provide an [authentication token](https://substreams.streamingfast.io/reference-and-specs/authentication). + +## Modules + +The modules in this repository answer some interesting questions when developing a blockchain application: + +### How Can You Get the Basic Information of a Block? + +For every block, the `map_block_meta` module retrieves the most relevant information of the block (number, hash, and parent hash). + +### How Can You Retrieve Transactions + +For every block, the `map_transactions` modules summaries transaction number of vin and vout, the total valut of btc sent + + +## Running the Substreams + +First, generate the Protobuf code, which are the outputs of the Substreams: + +``` +> make protogen +``` + +Then, build the Rust code using the `cargo` command-line tool: + +``` +> make build +``` + +Now, you are ready to run the Substreams. The Substreams contained in this project are independent of each other, so you must specify which Substreams module you want to run. + +### Running the "map_block_meta" Module + +In the following command, you retrieve the metadata of the block with number `819113`. You specify the starting block by using the `--start-block` parameter. + +```bash +> substreams run -e mainnet.btc.streamingfast.io:443 substreams.yaml map_block_meta --start-block 819113 --stop-block +1 +Connected (trace ID dabf2d0d5f8074a36da855579279e23c) +Progress messages received: 0 (0/sec) +Backprocessing history up to requested target block 819113: +(hit 'm' to switch mode) + + + + + +----------- BLOCK #819,113 (00000000000000000003aefe02ab07a4a7c5a27bb674b062732286a71ab1ab51) --------------- +{ + "@module": "map_block_meta", + "@block": 819113, + "@type": "btc.block_meta.v1.BlockMeta", + "@data": { + "number": "819113", + "hash": "00000000000000000003aefe02ab07a4a7c5a27bb674b062732286a71ab1ab51", + "parentHash": "000000000000000000001be3e5929be506d4e2c8cd1b7ba4fa9422032434368f" + } +} + +all done +``` \ No newline at end of file diff --git a/bitcoin-explorer/bitcoin.png b/bitcoin-explorer/bitcoin.png new file mode 100644 index 0000000..c20a1ab Binary files /dev/null and b/bitcoin-explorer/bitcoin.png differ diff --git a/bitcoin-explorer/proto/block_meta.proto b/bitcoin-explorer/proto/block_meta.proto new file mode 100644 index 0000000..9223ab9 --- /dev/null +++ b/bitcoin-explorer/proto/block_meta.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package btc.block_meta.v1; + +message BlockMeta { + uint64 number = 1; + string hash = 2; + string parent_hash = 3; +} \ No newline at end of file diff --git a/bitcoin-explorer/proto/transaction.proto b/bitcoin-explorer/proto/transaction.proto new file mode 100644 index 0000000..a76c5be --- /dev/null +++ b/bitcoin-explorer/proto/transaction.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package btc.transaction.v1; + +message Transactions { + repeated Transaction transactions = 1; +} + +message Transaction { + string hash = 1; + uint64 vin_count = 2; + uint64 vout_count = 3; + double btc_value = 4; +} \ No newline at end of file diff --git a/bitcoin-explorer/rust-toolchain.toml b/bitcoin-explorer/rust-toolchain.toml new file mode 100644 index 0000000..e892501 --- /dev/null +++ b/bitcoin-explorer/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.69" +components = [ "rustfmt" ] +targets = [ "wasm32-unknown-unknown" ] \ No newline at end of file diff --git a/bitcoin-explorer/src/lib.rs b/bitcoin-explorer/src/lib.rs new file mode 100644 index 0000000..034e508 --- /dev/null +++ b/bitcoin-explorer/src/lib.rs @@ -0,0 +1,4 @@ +mod map_block_meta; +mod map_block_full; +mod map_transactions; +mod pb; diff --git a/bitcoin-explorer/src/map_block_full.rs b/bitcoin-explorer/src/map_block_full.rs new file mode 100644 index 0000000..28f5d1f --- /dev/null +++ b/bitcoin-explorer/src/map_block_full.rs @@ -0,0 +1,6 @@ +use substreams_bitcoin::pb::btc::v1::Block; + +#[substreams::handlers::map] +fn map_block_full(blk: Block) -> Result { + Ok(blk) +} diff --git a/bitcoin-explorer/src/map_block_meta.rs b/bitcoin-explorer/src/map_block_meta.rs new file mode 100644 index 0000000..11b5d48 --- /dev/null +++ b/bitcoin-explorer/src/map_block_meta.rs @@ -0,0 +1,11 @@ +use crate::pb::btc::block_meta::v1::BlockMeta; +use substreams_bitcoin::pb::btc::v1::Block; + +#[substreams::handlers::map] +fn map_block_meta(blk: Block) -> Result { + Ok(BlockMeta { + number: blk.height as u64, + hash: blk.hash, + parent_hash: blk.previous_hash, + }) +} diff --git a/bitcoin-explorer/src/map_transactions.rs b/bitcoin-explorer/src/map_transactions.rs new file mode 100644 index 0000000..caf0f1b --- /dev/null +++ b/bitcoin-explorer/src/map_transactions.rs @@ -0,0 +1,17 @@ +use crate::pb::btc::transaction::v1::{Transaction, Transactions}; +use substreams_bitcoin::pb::btc::v1::{Block}; + +#[substreams::handlers::map] +fn map_transactions(blk: Block) -> Result> { + let transactions: Vec = blk + .transactions() + .map(|trans| Transaction { + hash: trans.txid.clone(), + vin_count: trans.vin.len() as u64, + vout_count: trans.vout.len() as u64, + btc_value: trans.vout.iter().map(|vout| vout.value).sum(), + }) + .collect(); + + Ok(Transactions { transactions }) +} \ No newline at end of file diff --git a/bitcoin-explorer/src/pb/btc.block_meta.v1.rs b/bitcoin-explorer/src/pb/btc.block_meta.v1.rs new file mode 100644 index 0000000..bc151ce --- /dev/null +++ b/bitcoin-explorer/src/pb/btc.block_meta.v1.rs @@ -0,0 +1,12 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BlockMeta { + #[prost(uint64, tag="1")] + pub number: u64, + #[prost(string, tag="2")] + pub hash: ::prost::alloc::string::String, + #[prost(string, tag="3")] + pub parent_hash: ::prost::alloc::string::String, +} +// @@protoc_insertion_point(module) diff --git a/bitcoin-explorer/src/pb/btc.transaction.v1.rs b/bitcoin-explorer/src/pb/btc.transaction.v1.rs new file mode 100644 index 0000000..bc612af --- /dev/null +++ b/bitcoin-explorer/src/pb/btc.transaction.v1.rs @@ -0,0 +1,20 @@ +// @generated +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transactions { + #[prost(message, repeated, tag="1")] + pub transactions: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Transaction { + #[prost(string, tag="1")] + pub hash: ::prost::alloc::string::String, + #[prost(uint64, tag="2")] + pub vin_count: u64, + #[prost(uint64, tag="3")] + pub vout_count: u64, + #[prost(double, tag="4")] + pub btc_value: f64, +} +// @@protoc_insertion_point(module) diff --git a/bitcoin-explorer/src/pb/mod.rs b/bitcoin-explorer/src/pb/mod.rs new file mode 100644 index 0000000..f36742a --- /dev/null +++ b/bitcoin-explorer/src/pb/mod.rs @@ -0,0 +1,17 @@ +// @generated +pub mod btc { + pub mod block_meta { + // @@protoc_insertion_point(attribute:btc.block_meta.v1) + pub mod v1 { + include!("btc.block_meta.v1.rs"); + // @@protoc_insertion_point(btc.block_meta.v1) + } + } + pub mod transaction { + // @@protoc_insertion_point(attribute:btc.transaction.v1) + pub mod v1 { + include!("btc.transaction.v1.rs"); + // @@protoc_insertion_point(btc.transaction.v1) + } + } +} diff --git a/bitcoin-explorer/substreams.yaml b/bitcoin-explorer/substreams.yaml new file mode 100644 index 0000000..f0f8ad7 --- /dev/null +++ b/bitcoin-explorer/substreams.yaml @@ -0,0 +1,53 @@ +specVersion: v0.1.0 +package: + name: "bitcoin_explorer" + image: ./bitcoin.png + url: "http://github.com/streamingfast/substreams-explorers/" + version: v0.1.0 + doc: | + This packages holds simple modules to allow you to explore the Bitcoin data model. + +imports: + bitcoin: ../../firehose-bitcoin/substreams/bitcoin-v1.0.0.spkg + +network: btc-mainnet + +protobuf: + files: + - block_meta.proto + - transaction.proto + importPaths: + - ./proto + +binaries: + default: + type: wasm/rust-v1 + file: ./target/wasm32-unknown-unknown/release/substreams.wasm + +modules: + - name: map_block_meta + kind: map + inputs: + - source: sf.bitcoin.type.v1.Block + output: + type: proto:btc.block_meta.v1.BlockMeta + doc: | + `map_block_meta` allows you to view a basic information about a block + + - name: map_block_full + kind: map + inputs: + - source: sf.bitcoin.type.v1.Block + output: + type: proto:sf.bitcoin.type.v1.Block + doc: | + `map_block_full` allows you to view a complete block, as received by a Substreams module + + - name: map_transactions + kind: map + inputs: + - source: sf.bitcoin.type.v1.Block + output: + type: proto:btc.transaction.v1.Transactions + doc: | + `map_filter_transaction` allows you to find a transaction by specifying either `to` or `from` value in the parameters. You might need to scope your search to the blocks you know you are going to find that transaction. Check with your preferred block explorer first.