Compare commits

...

10 Commits

Author SHA1 Message Date
nym21 10b496e845 release: v0.0.100 2025-09-07 17:14:10 +02:00
nym21 bbe7bf390d crates: upgrade rest 2025-09-07 17:13:57 +02:00
nym21 4777b3400a crates: upgrade seqdb 2025-09-07 17:13:01 +02:00
nym21 acaa70e944 release: v0.0.99 2025-09-07 17:01:58 +02:00
nym21 4049d694f7 global: snapshot + pools + fixes 2025-09-07 17:01:34 +02:00
nym21 e155a3dacf bitview: fix localstorage error 2025-09-06 15:41:16 +02:00
nym21 a224e4c4d8 release: v0.0.98 2025-09-05 14:50:46 +02:00
nym21 edaeda5424 release: v0.0.97 2025-09-05 14:47:35 +02:00
nym21 09d974913d computer: pools part 1 + fetcher: fix url + interface: more ddos protection 2025-09-05 14:47:11 +02:00
nym21 f82edb290a global: add datasets and charts 2025-09-05 10:00:29 +02:00
80 changed files with 4547 additions and 1317 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
# Builds
target
websites/dist
vecid-to-indexes.js
bridge/
/ids.txt
# Copies
Generated
+322 -75
View File
@@ -54,6 +54,28 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "allocative"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fac2ce611db8b8cee9b2aa886ca03c924e9da5e5295d0dbd0526e5d0b0710f7"
dependencies = [
"allocative_derive",
"ctor",
"parking_lot 0.11.2",
]
[[package]]
name = "allocative_derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe233a377643e0fc1a56421d7c90acdec45c291b30345eb9f08e8d0ddce5a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "allocator-api2"
version = "0.2.21"
@@ -482,7 +504,7 @@ dependencies = [
[[package]]
name = "brk"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"brk_bundler",
"brk_cli",
@@ -501,7 +523,7 @@ dependencies = [
[[package]]
name = "brk_bundler"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"brk_rolldown",
"log",
@@ -512,7 +534,7 @@ dependencies = [
[[package]]
name = "brk_cli"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"bitcoincore-rpc",
"brk_bundler",
@@ -537,8 +559,10 @@ dependencies = [
[[package]]
name = "brk_computer"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"allocative",
"allocative_derive",
"bitcoin",
"bitcoincore-rpc",
"brk_error",
@@ -546,12 +570,17 @@ dependencies = [
"brk_indexer",
"brk_logger",
"brk_parser",
"brk_store",
"brk_structs",
"derive_deref",
"inferno",
"jiff",
"log",
"num_enum",
"pco",
"rayon",
"serde",
"serde_json",
"vecdb",
"zerocopy",
"zerocopy-derive",
@@ -559,7 +588,7 @@ dependencies = [
[[package]]
name = "brk_error"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"bitcoincore-rpc",
"fjall",
@@ -572,7 +601,7 @@ dependencies = [
[[package]]
name = "brk_fetcher"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"brk_error",
"brk_logger",
@@ -584,7 +613,7 @@ dependencies = [
[[package]]
name = "brk_indexer"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -601,7 +630,7 @@ dependencies = [
[[package]]
name = "brk_interface"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"brk_computer",
"brk_error",
@@ -609,6 +638,7 @@ dependencies = [
"brk_structs",
"derive_deref",
"nucleo-matcher",
"quick_cache",
"schemars 1.0.4",
"serde",
"serde_json",
@@ -619,7 +649,7 @@ dependencies = [
[[package]]
name = "brk_logger"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"env_logger",
"jiff",
@@ -629,7 +659,7 @@ dependencies = [
[[package]]
name = "brk_mcp"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"axum",
"brk_interface",
@@ -639,7 +669,7 @@ dependencies = [
[[package]]
name = "brk_parser"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"bitcoin",
"bitcoincore-rpc",
@@ -1017,7 +1047,7 @@ dependencies = [
[[package]]
name = "brk_server"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"axum",
"bitcoincore-rpc",
@@ -1041,7 +1071,7 @@ dependencies = [
[[package]]
name = "brk_store"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"brk_error",
"brk_structs",
@@ -1064,8 +1094,10 @@ dependencies = [
[[package]]
name = "brk_structs"
version = "0.0.96"
version = "0.0.100"
dependencies = [
"allocative",
"allocative_derive",
"bitcoin",
"bitcoincore-rpc",
"brk_error",
@@ -1116,6 +1148,12 @@ version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]]
name = "bytemuck"
version = "1.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
[[package]]
name = "byteorder"
version = "1.5.0"
@@ -1145,9 +1183,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.35"
version = "1.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "590f9024a68a8c40351881787f1934dc11afd69090f5edb6831464694d836ea3"
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -1190,7 +1228,7 @@ dependencies = [
"num-traits",
"serde",
"wasm-bindgen",
"windows-link",
"windows-link 0.1.3",
]
[[package]]
@@ -1200,6 +1238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
@@ -1458,13 +1497,24 @@ dependencies = [
]
[[package]]
name = "ctrlc"
version = "3.4.7"
name = "ctor"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "ctrlc"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3"
dependencies = [
"dispatch",
"nix",
"windows-sys 0.59.0",
"windows-sys 0.61.0",
]
[[package]]
@@ -1548,7 +1598,7 @@ dependencies = [
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
"parking_lot_core 0.9.11",
]
[[package]]
@@ -1614,6 +1664,12 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "dispatch"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "displaydoc"
version = "0.2.5"
@@ -1768,9 +1824,9 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650"
checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
[[package]]
name = "fixedbitset"
@@ -1955,7 +2011,7 @@ dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.3+wasi-0.2.4",
"wasi 0.14.4+wasi-0.2.4",
]
[[package]]
@@ -2287,6 +2343,28 @@ dependencies = [
"cfb",
]
[[package]]
name = "inferno"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e96d2465363ed2d81857759fc864cf6bb7997f79327aec028d65bd7989393685"
dependencies = [
"ahash",
"clap",
"crossbeam-channel",
"crossbeam-utils",
"dashmap",
"env_logger",
"indexmap 2.11.0",
"itoa",
"log",
"num-format",
"once_cell",
"quick-xml",
"rgb",
"str_stack",
]
[[package]]
name = "inotify"
version = "0.11.0"
@@ -2307,6 +2385,15 @@ dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
]
[[package]]
name = "interval-heap"
version = "0.0.5"
@@ -2401,9 +2488,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.77"
version = "0.3.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -2470,7 +2557,7 @@ checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
"bitflags 2.9.4",
"libc",
"redox_syscall",
"redox_syscall 0.5.17",
]
[[package]]
@@ -2506,9 +2593,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.27"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]]
name = "lsm-tree"
@@ -2578,11 +2665,10 @@ dependencies = [
[[package]]
name = "minreq"
version = "2.14.0"
version = "2.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84885312a86831bff4a3cb04a1e54a3f698407e3274c83249313f194d3e0b678"
checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d"
dependencies = [
"log",
"rustls",
"rustls-webpki",
"serde",
@@ -2697,6 +2783,16 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-format"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
dependencies = [
"arrayvec",
"itoa",
]
[[package]]
name = "num-integer"
version = "0.1.46"
@@ -2715,6 +2811,28 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
dependencies = [
"num_enum_derive",
"rustversion",
]
[[package]]
name = "num_enum_derive"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "object"
version = "0.36.7"
@@ -3239,6 +3357,17 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core 0.8.6",
]
[[package]]
name = "parking_lot"
version = "0.12.4"
@@ -3246,7 +3375,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
dependencies = [
"lock_api",
"parking_lot_core",
"parking_lot_core 0.9.11",
]
[[package]]
name = "parking_lot_core"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall 0.2.16",
"smallvec",
"winapi",
]
[[package]]
@@ -3257,7 +3400,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"redox_syscall 0.5.17",
"smallvec",
"windows-targets 0.52.6",
]
@@ -3468,6 +3611,15 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro-crate"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro-error-attr2"
version = "2.0.0"
@@ -3499,6 +3651,15 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-xml"
version = "0.37.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
dependencies = [
"memchr",
]
[[package]]
name = "quick_cache"
version = "0.6.16"
@@ -3508,7 +3669,7 @@ dependencies = [
"ahash",
"equivalent",
"hashbrown 0.15.5",
"parking_lot",
"parking_lot 0.12.4",
]
[[package]]
@@ -3633,6 +3794,15 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.5.17"
@@ -3701,6 +3871,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "rgb"
version = "0.8.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"
dependencies = [
"bytemuck",
]
[[package]]
name = "ring"
version = "0.17.14"
@@ -3902,14 +4081,16 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
[[package]]
name = "seqdb"
version = "0.2.9"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade192d6f8a1e58c43428c8e194016124f20744f75cb14e2fcc0c79309fe4f91"
checksum = "3078349d3b0b862848f518737b1228fdbaa725819688036db54363aa6c960ead"
dependencies = [
"allocative",
"allocative_derive",
"libc",
"log",
"memmap2",
"parking_lot",
"parking_lot 0.12.4",
"rayon",
"zerocopy",
"zerocopy-derive",
@@ -4140,6 +4321,12 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6"
[[package]]
name = "str_stack"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
[[package]]
name = "strsim"
version = "0.11.1"
@@ -4408,12 +4595,18 @@ dependencies = [
"indexmap 2.11.0",
"serde",
"serde_spanned",
"toml_datetime",
"toml_datetime 0.7.0",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
[[package]]
name = "toml_datetime"
version = "0.7.0"
@@ -4423,6 +4616,17 @@ dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap 2.11.0",
"toml_datetime 0.6.11",
"winnow",
]
[[package]]
name = "toml_parser"
version = "1.0.2"
@@ -4735,13 +4939,15 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"
[[package]]
name = "vecdb"
version = "0.2.9"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c3e103eeb634851690d815a886ba8fe1ab21d2f520d915c411979bc76de8419"
checksum = "9f3b3745eeee3b56f0db302a3ccaa2b400b5c881adf7319afde753b2fed83aae"
dependencies = [
"allocative",
"allocative_derive",
"ctrlc",
"log",
"parking_lot",
"parking_lot 0.12.4",
"pco",
"rayon",
"seqdb",
@@ -4755,9 +4961,9 @@ dependencies = [
[[package]]
name = "vecdb_derive"
version = "0.2.9"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdf71ae8eeaf2f187cee599e8e34a49bf6fd0536977bd009d94be35e3801754"
checksum = "cb14e5900ae8ba26112c438311b274de59e566a180d7795a584a83e3faa5cb9f"
dependencies = [
"quote",
"syn 2.0.106",
@@ -4808,30 +5014,31 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
version = "0.14.3+wasi-0.2.4"
version = "0.14.4+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95"
checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a"
dependencies = [
"wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb"
dependencies = [
"bumpalo",
"log",
@@ -4843,9 +5050,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -4853,9 +5060,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
dependencies = [
"proc-macro2",
"quote",
@@ -4866,9 +5073,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.100"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1"
dependencies = [
"unicode-ident",
]
@@ -4880,14 +5087,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]]
name = "winapi-util"
version = "0.1.10"
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"windows-sys 0.60.2",
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.0",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.61.2"
@@ -4896,7 +5125,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-link 0.1.3",
"windows-result",
"windows-strings",
]
@@ -4929,13 +5158,19 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-result"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link",
"windows-link 0.1.3",
]
[[package]]
@@ -4944,7 +5179,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link",
"windows-link 0.1.3",
]
[[package]]
@@ -4974,6 +5209,15 @@ dependencies = [
"windows-targets 0.53.3",
]
[[package]]
name = "windows-sys"
version = "0.61.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa"
dependencies = [
"windows-link 0.2.0",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
@@ -4996,7 +5240,7 @@ version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows-link 0.1.3",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
@@ -5108,12 +5352,15 @@ name = "winnow"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen"
version = "0.45.0"
version = "0.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814"
checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36"
[[package]]
name = "writeable"
@@ -5159,18 +5406,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.26"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.26"
version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
@@ -5233,9 +5480,9 @@ dependencies = [
[[package]]
name = "zip"
version = "4.6.1"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1"
checksum = "b9fdfa5f34b5980f2c21b3a2c68c09ade4debddc7be52c51056695effc73a08c"
dependencies = [
"arbitrary",
"crc32fast",
@@ -5283,9 +5530,9 @@ dependencies = [
[[package]]
name = "zstd-sys"
version = "2.0.15+zstd.1.5.7"
version = "2.0.16+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
dependencies = [
"cc",
"pkg-config",
+22 -19
View File
@@ -4,7 +4,7 @@ members = ["crates/*"]
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
package.license = "MIT"
package.edition = "2024"
package.version = "0.0.96"
package.version = "0.0.100"
package.homepage = "https://bitcoinresearchkit.org"
package.repository = "https://github.com/bitcoinresearchkit/brk"
package.readme = "README.md"
@@ -23,29 +23,32 @@ debug = true
inherits = "release"
[workspace.dependencies]
allocative = { version = "0.3.4", features = ["parking_lot"] }
allocative_derive = "0.3.3"
axum = "0.8.4"
bitcoin = { version = "0.32.7", features = ["serde"] }
bitcoincore-rpc = "0.19.0"
brk_bundler = { version = "0.0.96", path = "crates/brk_bundler" }
brk_cli = { version = "0.0.96", path = "crates/brk_cli" }
brk_computer = { version = "0.0.96", path = "crates/brk_computer" }
brk_error = { version = "0.0.96", path = "crates/brk_error" }
brk_fetcher = { version = "0.0.96", path = "crates/brk_fetcher" }
brk_indexer = { version = "0.0.96", path = "crates/brk_indexer" }
brk_interface = { version = "0.0.96", path = "crates/brk_interface" }
brk_logger = { version = "0.0.96", path = "crates/brk_logger" }
brk_mcp = { version = "0.0.96", path = "crates/brk_mcp" }
brk_parser = { version = "0.0.96", path = "crates/brk_parser" }
brk_server = { version = "0.0.96", path = "crates/brk_server" }
brk_store = { version = "0.0.96", path = "crates/brk_store" }
brk_structs = { version = "0.0.96", path = "crates/brk_structs" }
brk_bundler = { version = "0.0.100", path = "crates/brk_bundler" }
brk_cli = { version = "0.0.100", path = "crates/brk_cli" }
brk_computer = { version = "0.0.100", path = "crates/brk_computer" }
brk_error = { version = "0.0.100", path = "crates/brk_error" }
brk_fetcher = { version = "0.0.100", path = "crates/brk_fetcher" }
brk_indexer = { version = "0.0.100", path = "crates/brk_indexer" }
brk_interface = { version = "0.0.100", path = "crates/brk_interface" }
brk_logger = { version = "0.0.100", path = "crates/brk_logger" }
brk_mcp = { version = "0.0.100", path = "crates/brk_mcp" }
brk_parser = { version = "0.0.100", path = "crates/brk_parser" }
brk_server = { version = "0.0.100", path = "crates/brk_server" }
brk_store = { version = "0.0.100", path = "crates/brk_store" }
brk_structs = { version = "0.0.100", path = "crates/brk_structs" }
byteview = "=0.6.1"
derive_deref = "1.1.1"
fjall = "2.11.2"
jiff = "0.2.15"
log = "0.4.27"
minreq = { version = "2.14.0", features = ["https", "serde_json"] }
log = "0.4.28"
minreq = { version = "2.14.1", features = ["https", "serde_json"] }
parking_lot = "0.12.4"
quick_cache = "0.6.16"
rayon = "1.11.0"
serde = "1.0.219"
serde_bytes = "0.11.17"
@@ -53,9 +56,9 @@ serde_derive = "1.0.219"
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
vecdb = { version = "0.2.9", features = ["derive"]}
zerocopy = "0.8.26"
zerocopy-derive = "0.8.26"
vecdb = { version = "0.2.11", features = ["derive"]}
zerocopy = "0.8.27"
zerocopy-derive = "0.8.27"
[workspace.metadata.release]
shared-version = true
+1 -3
View File
@@ -64,11 +64,9 @@
- miners
- maybe xpubs
- charts
- improve some names and colors
- remove `sum` series when it's a duplicate of the `base` (in subsidy for example)
- improve names and colors
- selected unit sometimes changes when going back end forth
- add support for custom charts
- separate z-score charts from "realized price" (with their own prices), have 4y, 2y and 1y
- price scale format depends on unit, hide digits for sats for example (if/when possible)
- table
- pagination
+3 -1
View File
@@ -35,7 +35,9 @@ pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> i
..Default::default()
});
bundler.write().await.unwrap();
if let Err(error) = bundler.write().await {
error!("{error:?}");
}
let absolute_source_index_path = source_path.join("index.html").absolutize();
let absolute_source_index_path_clone = absolute_source_index_path.clone();
+1 -1
View File
@@ -28,7 +28,7 @@ minreq = { workspace = true }
serde = { workspace = true }
tokio = { workspace = true }
toml = "0.9.5"
zip = { version = "4.6.1", default-features = false, features = ["deflate"] }
zip = { version = "5.0.0", default-features = false, features = ["deflate"] }
[[bin]]
name = "brk"
+98 -55
View File
@@ -1,19 +1,20 @@
use std::{fs, io, path::Path};
use brk_computer::pools;
use brk_interface::{Index, Interface};
use brk_server::VERSION;
use crate::website::Website;
const SCRIPTS: &str = "scripts";
const BRIDGE_PATH: &str = "scripts/bridge";
#[allow(clippy::upper_case_acronyms)]
pub trait Bridge {
fn generate_bridge_file(&self, website: Website, websites_path: &Path) -> io::Result<()>;
fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()>;
}
impl Bridge for Interface<'static> {
fn generate_bridge_file(&self, website: Website, websites_path: &Path) -> io::Result<()> {
fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()> {
if website.is_none() {
return Ok(());
}
@@ -24,88 +25,130 @@ impl Bridge for Interface<'static> {
return Ok(());
}
let path = path.join(SCRIPTS);
let path = path.join(BRIDGE_PATH);
fs::create_dir_all(&path)?;
let path = path.join(Path::new("vecid-to-indexes.js"));
generate_vecs_file(self, &path)?;
generate_pools_file(&path)
}
}
let indexes = Index::all();
fn generate_pools_file(parent: &Path) -> io::Result<()> {
let path = parent.join(Path::new("pools.js"));
let mut contents = format!(
"//
let pools = pools();
let mut contents = "//
// File auto-generated, any modifications will be overwritten
//
"
.to_string();
contents += "
/** @typedef {ReturnType<typeof createPools>} Pools */
/** @typedef {keyof Pools} Pool */
export function createPools() {
return /** @type {const} */ ({
";
let mut sorted_pools: Vec<_> = pools.iter().collect();
sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
contents += &sorted_pools
.iter()
.map(|pool| {
let id = pool.serialized_id();
format!(" {id}: \"{}\",", pool.name)
})
.collect::<Vec<_>>()
.join("\n");
contents += "\n });\n}\n";
fs::write(path, contents)
}
fn generate_vecs_file(interface: &Interface<'static>, parent: &Path) -> io::Result<()> {
let path = parent.join(Path::new("vecs.js"));
let indexes = Index::all();
let mut contents = format!(
"//
// File auto-generated, any modifications will be overwritten
//
export const VERSION = \"v{VERSION}\";
"
);
);
contents += &indexes
contents += &indexes
.iter()
.enumerate()
.map(|(i_of_i, i)| {
// let lowered = i.to_string().to_lowercase();
format!("/** @typedef {{{i_of_i}}} {i} */",)
})
.collect::<Vec<_>>()
.join("\n");
contents += &format!(
"\n\n/** @typedef {{{}}} Index */\n",
indexes
.iter()
.enumerate()
.map(|(i_of_i, i)| {
// let lowered = i.to_string().to_lowercase();
format!("/** @typedef {{{i_of_i}}} {i} */",)
})
.map(|i| i.to_string())
.collect::<Vec<_>>()
.join("\n");
.join(" | ")
);
contents += &format!(
"\n\n/** @typedef {{{}}} Index */\n",
indexes
.iter()
.map(|i| i.to_string())
.collect::<Vec<_>>()
.join(" | ")
);
contents += "
contents += "
/** @typedef {ReturnType<typeof createIndexes>} Indexes */
export function createIndexes() {
return {
return {
";
contents += &indexes
.iter()
.enumerate()
.map(|(i_of_i, i)| {
let lowered = i.to_string().to_lowercase();
format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",)
})
.collect::<Vec<_>>()
.join("\n");
contents += &indexes
.iter()
.enumerate()
.map(|(i_of_i, i)| {
let lowered = i.to_string().to_lowercase();
format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",)
})
.collect::<Vec<_>>()
.join("\n");
contents += " };\n}\n";
contents += " };\n}\n";
contents += "
contents += "
/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes
/** @typedef {keyof VecIdToIndexes} VecId */
/**
* @returns {Record<any, number[]>}
*/
* @returns {Record<any, number[]>}
*/
export function createVecIdToIndexes() {
return {
return {
";
self.id_to_index_to_vec()
.iter()
.for_each(|(id, index_to_vec)| {
let indexes = index_to_vec
.keys()
.map(|i| (*i as u8).to_string())
// .map(|i| i.to_string())
.collect::<Vec<_>>()
.join(", ");
interface
.id_to_index_to_vec()
.iter()
.for_each(|(id, index_to_vec)| {
let indexes = index_to_vec
.keys()
.map(|i| (*i as u8).to_string())
// .map(|i| i.to_string())
.collect::<Vec<_>>()
.join(", ");
contents += &format!(" \"{id}\": [{indexes}],\n");
});
contents += &format!(" \"{id}\": [{indexes}],\n");
});
contents += " };\n}\n";
contents += " };\n}\n";
fs::write(path, contents)
}
fs::write(path, contents)
}
-1
View File
@@ -6,7 +6,6 @@ use std::{
use bitcoincore_rpc::{self, Auth, Client};
use brk_fetcher::Fetcher;
use clap::Parser;
use clap_derive::Parser;
use color_eyre::eyre::eyre;
use serde::{Deserialize, Deserializer, Serialize};
+3 -1
View File
@@ -107,7 +107,7 @@ pub fn run() -> color_eyre::Result<()> {
downloaded_websites_path
};
interface.generate_bridge_file(website, websites_path.as_path())?;
interface.generate_bridge_files(website, websites_path.as_path())?;
Some(bundle(&websites_path, website.to_folder_name(), true).await?)
} else {
@@ -135,6 +135,8 @@ pub fn run() -> color_eyre::Result<()> {
let starting_indexes =
indexer.index(&parser, rpc, &exit, config.check_collisions()).unwrap();
// dbg!(&starting_indexes);
computer.compute(&indexer, starting_indexes, &exit).unwrap();
info!("Waiting for new blocks...");
+1
View File
@@ -2,6 +2,7 @@ use clap_derive::ValueEnum;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, ValueEnum)]
#[serde(rename_all = "lowercase")]
pub enum Website {
None,
Bitview,
+7
View File
@@ -10,6 +10,8 @@ rust-version.workspace = true
build = "build.rs"
[dependencies]
allocative = { workspace = true }
allocative_derive = { workspace = true }
bitcoin = { workspace = true }
bitcoincore-rpc = { workspace = true }
brk_structs = { workspace = true }
@@ -17,13 +19,18 @@ brk_error = { workspace = true }
brk_fetcher = { workspace = true }
brk_indexer = { workspace = true }
brk_logger = { workspace = true }
brk_store = { workspace = true }
brk_parser = { workspace = true }
vecdb = { workspace = true }
derive_deref = { workspace = true }
inferno = "0.12.3"
jiff = { workspace = true }
log = { workspace = true }
num_enum = "0.7.4"
pco = "0.4.6"
rayon = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
zerocopy = { workspace = true }
zerocopy-derive = { workspace = true }
+125
View File
@@ -0,0 +1,125 @@
use std::{collections::BTreeMap, path::Path, thread};
use brk_computer::{Computer, pools};
use brk_error::Result;
use brk_fetcher::Fetcher;
use brk_indexer::Indexer;
use brk_structs::{AddressBytes, OutputIndex, OutputType};
use vecdb::{AnyIterableVec, Exit, VecIterator};
fn main() -> Result<()> {
brk_logger::init(Some(Path::new(".log")))?;
let exit = Exit::new();
exit.set_ctrlc_handler();
thread::Builder::new()
.stack_size(256 * 1024 * 1024)
.spawn(move || -> Result<()> {
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
let indexer = Indexer::forced_import(&outputs_dir)?;
let fetcher = Fetcher::import(true, None)?;
let computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?;
let pools = pools();
let mut res: BTreeMap<&'static str, usize> = BTreeMap::default();
let vecs = indexer.vecs;
let stores = indexer.stores;
let mut height_to_first_txindex_iter = vecs.height_to_first_txindex.iter();
let mut txindex_to_first_outputindex_iter = vecs.txindex_to_first_outputindex.iter();
let mut txindex_to_output_count_iter = computer.indexes.txindex_to_output_count.iter();
let mut outputindex_to_outputtype_iter = vecs.outputindex_to_outputtype.iter();
let mut outputindex_to_typeindex_iter = vecs.outputindex_to_typeindex.iter();
let mut p2pk65addressindex_to_p2pk65bytes_iter =
vecs.p2pk65addressindex_to_p2pk65bytes.iter();
let mut p2pk33addressindex_to_p2pk33bytes_iter =
vecs.p2pk33addressindex_to_p2pk33bytes.iter();
let mut p2pkhaddressindex_to_p2pkhbytes_iter =
vecs.p2pkhaddressindex_to_p2pkhbytes.iter();
let mut p2shaddressindex_to_p2shbytes_iter = vecs.p2shaddressindex_to_p2shbytes.iter();
let mut p2wpkhaddressindex_to_p2wpkhbytes_iter =
vecs.p2wpkhaddressindex_to_p2wpkhbytes.iter();
let mut p2wshaddressindex_to_p2wshbytes_iter =
vecs.p2wshaddressindex_to_p2wshbytes.iter();
let mut p2traddressindex_to_p2trbytes_iter = vecs.p2traddressindex_to_p2trbytes.iter();
let mut p2aaddressindex_to_p2abytes_iter = vecs.p2aaddressindex_to_p2abytes.iter();
let unknown = pools.get_unknown();
stores
.height_to_coinbase_tag
.iter()
.for_each(|(height, coinbase_tag)| {
let txindex = height_to_first_txindex_iter.unwrap_get_inner(height);
let outputindex = txindex_to_first_outputindex_iter.unwrap_get_inner(txindex);
let outputcount = txindex_to_output_count_iter.unwrap_get_inner(txindex);
let pool = (*outputindex..(*outputindex + *outputcount))
.map(OutputIndex::from)
.find_map(|outputindex| {
let outputtype =
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
let typeindex =
outputindex_to_typeindex_iter.unwrap_get_inner(outputindex);
let address = match outputtype {
OutputType::P2PK65 => Some(AddressBytes::from(
p2pk65addressindex_to_p2pk65bytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2PK33 => Some(AddressBytes::from(
p2pk33addressindex_to_p2pk33bytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2PKH => Some(AddressBytes::from(
p2pkhaddressindex_to_p2pkhbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2SH => Some(AddressBytes::from(
p2shaddressindex_to_p2shbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2WPKH => Some(AddressBytes::from(
p2wpkhaddressindex_to_p2wpkhbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2WSH => Some(AddressBytes::from(
p2wshaddressindex_to_p2wshbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2TR => Some(AddressBytes::from(
p2traddressindex_to_p2trbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2A => Some(AddressBytes::from(
p2aaddressindex_to_p2abytes_iter
.unwrap_get_inner(typeindex.into()),
)),
_ => None,
};
address
.and_then(|address| pools.find_from_address(&address.to_string()))
})
.or_else(|| pools.find_from_coinbase_tag(&coinbase_tag))
.unwrap_or(unknown);
*res.entry(pool.name).or_default() += 1;
});
let mut v = res.into_iter().map(|(k, v)| (v, k)).collect::<Vec<_>>();
v.sort_unstable();
println!("{:#?}", v);
println!("{:#?}", v.len());
Ok(())
})?
.join()
.unwrap()
}
+161 -7
View File
@@ -1,11 +1,13 @@
use std::path::Path;
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{
CheckedSub, Date, DateIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch, Height,
InputIndex, OutputIndex, Sats, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64,
Timestamp, TxIndex, TxVersion, Version, Weight,
CheckedSub, Date, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch,
Height, InputIndex, MonthIndex, OutputIndex, QuarterIndex, Sats, SemesterIndex, StoredBool,
StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Version, WeekIndex,
Weight, YearIndex,
};
use vecdb::{
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
@@ -20,18 +22,39 @@ use crate::grouped::{
use super::{Indexes, indexes, price};
const VERSION: Version = Version::ZERO;
const TARGET_BLOCKS_PER_DAY: f64 = 144.0;
const TARGET_BLOCKS_PER_DAY_F64: f64 = 144.0;
const TARGET_BLOCKS_PER_DAY: u64 = 144;
const TARGET_BLOCKS_PER_WEEK: u64 = 7 * TARGET_BLOCKS_PER_DAY;
const TARGET_BLOCKS_PER_MONTH: u64 = 30 * TARGET_BLOCKS_PER_DAY;
const TARGET_BLOCKS_PER_QUARTER: u64 = 3 * TARGET_BLOCKS_PER_MONTH;
const TARGET_BLOCKS_PER_SEMESTER: u64 = 2 * TARGET_BLOCKS_PER_QUARTER;
const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER;
const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR;
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct Vecs {
db: Database,
pub dateindex_to_block_count_target: LazyVecFrom1<DateIndex, StoredU64, DateIndex, DateIndex>,
pub weekindex_to_block_count_target: LazyVecFrom1<WeekIndex, StoredU64, WeekIndex, WeekIndex>,
pub monthindex_to_block_count_target:
LazyVecFrom1<MonthIndex, StoredU64, MonthIndex, MonthIndex>,
pub quarterindex_to_block_count_target:
LazyVecFrom1<QuarterIndex, StoredU64, QuarterIndex, QuarterIndex>,
pub semesterindex_to_block_count_target:
LazyVecFrom1<SemesterIndex, StoredU64, SemesterIndex, SemesterIndex>,
pub yearindex_to_block_count_target: LazyVecFrom1<YearIndex, StoredU64, YearIndex, YearIndex>,
pub decadeindex_to_block_count_target:
LazyVecFrom1<DecadeIndex, StoredU64, DecadeIndex, DecadeIndex>,
pub height_to_interval: EagerVec<Height, Timestamp>,
pub height_to_vbytes: EagerVec<Height, StoredU64>,
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_1w_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_1m_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_1y_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
@@ -39,7 +62,6 @@ pub struct Vecs {
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_fee: ComputedValueVecsFromTxindex,
@@ -288,7 +310,57 @@ impl Vecs {
let txindex_to_fee_rate =
EagerVec::forced_import_compressed(&db, "fee_rate", version + VERSION + Version::ZERO)?;
let dateindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.dateindex_to_dateindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
);
let weekindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.weekindex_to_weekindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
);
let monthindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.monthindex_to_monthindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
);
let quarterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.quarterindex_to_quarterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
);
let semesterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.semesterindex_to_semesterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
);
let yearindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.yearindex_to_yearindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
);
let decadeindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + VERSION + Version::ZERO,
indexes.decadeindex_to_decadeindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
);
let this = Self {
dateindex_to_block_count_target,
weekindex_to_block_count_target,
monthindex_to_block_count_target,
quarterindex_to_block_count_target,
semesterindex_to_block_count_target,
yearindex_to_block_count_target,
decadeindex_to_block_count_target,
height_to_interval: EagerVec::forced_import_compressed(
&db,
"interval",
@@ -321,6 +393,30 @@ impl Vecs {
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
indexes_to_1w_block_count: ComputedVecsFromDateIndex::forced_import(
&db,
"1w_block_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1m_block_count: ComputedVecsFromDateIndex::forced_import(
&db,
"1m_block_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1y_block_count: ComputedVecsFromDateIndex::forced_import(
&db,
"1y_block_count",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
&db,
"block_weight",
@@ -869,6 +965,54 @@ impl Vecs {
},
)?;
self.indexes_to_1w_block_count.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
7,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1m_block_count.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
30,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1y_block_count.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
365,
exit,
)?;
Ok(())
},
)?;
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
self.height_to_interval.compute_transform(
starting_indexes.height,
@@ -1538,7 +1682,7 @@ impl Vecs {
i,
StoredF64::from(
(f64::from(block_count_sum)
/ (target_multiplier * TARGET_BLOCKS_PER_DAY))
/ (target_multiplier * TARGET_BLOCKS_PER_DAY_F64))
* f64::from(difficulty_as_hash),
),
)
@@ -1686,6 +1830,13 @@ impl Vecs {
&self.txindex_to_weight,
&self.dateindex_to_fee_dominance,
&self.dateindex_to_subsidy_dominance,
&self.dateindex_to_block_count_target,
&self.weekindex_to_block_count_target,
&self.monthindex_to_block_count_target,
&self.quarterindex_to_block_count_target,
&self.semesterindex_to_block_count_target,
&self.yearindex_to_block_count_target,
&self.decadeindex_to_block_count_target,
],
self.indexes_to_hash_rate.vecs(),
self.indexes_to_hash_rate_1w_sma.vecs(),
@@ -1694,6 +1845,9 @@ impl Vecs {
self.indexes_to_hash_rate_1y_sma.vecs(),
self.timeindexes_to_timestamp.vecs(),
self.indexes_to_block_count.vecs(),
self.indexes_to_1w_block_count.vecs(),
self.indexes_to_1m_block_count.vecs(),
self.indexes_to_1y_block_count.vecs(),
self.indexes_to_block_interval.vecs(),
self.indexes_to_block_size.vecs(),
self.indexes_to_block_vbytes.vecs(),
-11
View File
@@ -26,7 +26,6 @@ pub struct Vecs {
pub constant_4: ComputedVecsFromHeight<StoredU16>,
pub constant_50: ComputedVecsFromHeight<StoredU16>,
pub constant_100: ComputedVecsFromHeight<StoredU16>,
pub constant_144: ComputedVecsFromHeight<StoredU16>,
pub constant_600: ComputedVecsFromHeight<StoredU16>,
pub constant_minus_1: ComputedVecsFromHeight<StoredI16>,
pub constant_minus_2: ComputedVecsFromHeight<StoredI16>,
@@ -95,14 +94,6 @@ impl Vecs {
indexes,
VecBuilderOptions::default().add_last(),
)?,
constant_144: ComputedVecsFromHeight::forced_import(
&db,
"constant_144",
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
constant_600: ComputedVecsFromHeight::forced_import(
&db,
"constant_600",
@@ -184,7 +175,6 @@ impl Vecs {
(&mut self.constant_4, 4),
(&mut self.constant_50, 50),
(&mut self.constant_100, 100),
(&mut self.constant_144, 144),
(&mut self.constant_600, 600),
]
.into_iter()
@@ -245,7 +235,6 @@ impl Vecs {
self.constant_4.vecs(),
self.constant_50.vecs(),
self.constant_100.vecs(),
self.constant_144.vecs(),
self.constant_600.vecs(),
self.constant_minus_1.vecs(),
self.constant_minus_2.vecs(),
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_error::{Error, Result};
use brk_structs::{CheckedSub, StoredU64, Version};
use vecdb::{
@@ -9,7 +10,7 @@ use crate::utils::get_percentile;
use super::ComputedType;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Allocative)]
pub struct EagerVecBuilder<I, T>
where
I: StoredIndex,
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_structs::Version;
use vecdb::{
AnyBoxedIterableVec, AnyCloneableIterableVec, AnyCollectableVec, FromCoarserIndex,
@@ -9,7 +10,7 @@ use crate::grouped::{EagerVecBuilder, VecBuilderOptions};
use super::ComputedType;
#[allow(clippy::type_complexity)]
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct LazyVecBuilder<I, T, S1I, S2T>
where
I: StoredIndex,
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
@@ -10,7 +11,7 @@ use crate::{Indexes, grouped::LazyVecBuilder, indexes};
use super::{ComputedType, EagerVecBuilder, Source, VecBuilderOptions};
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct ComputedVecsFromDateIndex<T>
where
T: ComputedType + PartialOrd,
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
@@ -15,7 +16,7 @@ use crate::{
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct ComputedVecsFromHeight<T>
where
T: ComputedType + PartialOrd,
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{
@@ -17,7 +18,7 @@ use crate::{
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct ComputedVecsFromTxindex<T>
where
T: ComputedType + PartialOrd,
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{Bitcoin, Dollars, Height, Sats, Version};
@@ -12,7 +13,7 @@ use crate::{
use super::{ComputedVecsFromHeight, VecBuilderOptions};
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct ComputedValueVecsFromHeight {
pub sats: ComputedVecsFromHeight<Sats>,
pub bitcoin: ComputedVecsFromHeight<Bitcoin>,
@@ -1,3 +1,4 @@
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{Bitcoin, Close, Dollars, Height, Sats, TxIndex, Version};
@@ -10,7 +11,7 @@ use crate::{Indexes, grouped::Source, indexes, price};
use super::{ComputedVecsFromTxindex, VecBuilderOptions};
#[derive(Clone)]
#[derive(Clone, Allocative)]
pub struct ComputedValueVecsFromTxindex {
pub sats: ComputedVecsFromTxindex<Sats>,
pub bitcoin_txindex: LazyVecFrom1<TxIndex, Bitcoin, TxIndex, Sats>,
+67 -14
View File
@@ -1,6 +1,6 @@
#![doc = include_str!("../README.md")]
use std::{path::Path, thread};
use std::path::Path;
use brk_error::Result;
use brk_fetcher::Fetcher;
@@ -16,6 +16,7 @@ mod fetched;
mod grouped;
mod indexes;
mod market;
mod pools;
mod price;
mod stateful;
mod states;
@@ -24,6 +25,7 @@ mod utils;
use indexes::Indexes;
pub use pools::*;
pub use states::PriceToAmount;
use states::*;
@@ -32,6 +34,7 @@ pub struct Computer {
pub indexes: indexes::Vecs,
pub constants: constants::Vecs,
pub market: market::Vecs,
pub pools: pools::Vecs,
pub price: Option<price::Vecs>,
pub chain: chain::Vecs,
pub stateful: stateful::Vecs,
@@ -39,7 +42,7 @@ pub struct Computer {
pub cointime: cointime::Vecs,
}
const VERSION: Version = Version::TWO;
const VERSION: Version = Version::new(4);
impl Computer {
/// Do NOT import multiple times or things will break !!!
@@ -84,6 +87,12 @@ impl Computer {
&indexes,
price.as_ref(),
)?,
pools: pools::Vecs::forced_import(
&computed_path,
VERSION + Version::ZERO,
&indexes,
price.as_ref(),
)?,
cointime: cointime::Vecs::forced_import(
&computed_path,
VERSION + Version::ZERO,
@@ -123,8 +132,8 @@ impl Computer {
)?;
}
thread::scope(|scope| -> Result<()> {
let chain = scope.spawn(|| {
std::thread::scope(|scope| -> Result<()> {
let chain = scope.spawn(|| -> Result<()> {
info!("Computing chain...");
self.chain.compute(
indexer,
@@ -132,23 +141,33 @@ impl Computer {
&starting_indexes,
self.price.as_ref(),
exit,
)
});
let market = scope.spawn(|| -> Result<()> {
if let Some(price) = self.price.as_ref() {
info!("Computing market...");
self.market
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
}
)?;
Ok(())
});
if let Some(price) = self.price.as_ref() {
info!("Computing market...");
self.market
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
}
// let _ = generate_allocation_files(&self.pools);
chain.join().unwrap()?;
market.join().unwrap()?;
Ok(())
})?;
self.pools.compute(
indexer,
&self.indexes,
&starting_indexes,
&self.chain,
self.price.as_ref(),
exit,
)?;
// return Ok(());
info!("Computing stateful...");
self.stateful.compute(
indexer,
@@ -181,6 +200,7 @@ impl Computer {
self.chain.vecs(),
self.stateful.vecs(),
self.cointime.vecs(),
self.pools.vecs(),
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
self.price.as_ref().map_or(vec![], |v| v.vecs()),
]
@@ -193,3 +213,36 @@ impl Computer {
Box::leak(Box::new(self.clone()))
}
}
// pub fn generate_allocation_files(monitored: &pools::Vecs) -> Result<()> {
// info!("Generating Allocative files...");
// let mut flamegraph = allocative::FlameGraphBuilder::default();
// flamegraph.visit_root(monitored);
// let output = flamegraph.finish();
// let folder = format!(
// "at-{}",
// jiff::Timestamp::now().strftime("%Y-%m-%d_%Hh%Mm%Ss"),
// );
// let path = std::path::PathBuf::from(&format!("./target/flamegraph/{folder}"));
// std::fs::create_dir_all(&path)?;
// // fs::write(path.join("flamegraph.src"), &output.flamegraph())?;
// let mut fg_svg = Vec::new();
// inferno::flamegraph::from_reader(
// &mut inferno::flamegraph::Options::default(),
// output.flamegraph().write().as_bytes(),
// &mut fg_svg,
// )?;
// std::fs::write(path.join("flamegraph.svg"), &fg_svg)?;
// std::fs::write(path.join("warnings.txt"), output.warnings())?;
// info!("Successfully generated Allocative files");
// Ok(())
// }
+287
View File
@@ -0,0 +1,287 @@
use allocative::Allocative;
use num_enum::{FromPrimitive, IntoPrimitive};
use serde::{Deserialize, Serialize};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
// Created from the list in `pools.rs`
// Can be used as index for said list
#[allow(clippy::upper_case_acronyms)]
#[derive(
Debug,
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
FromPrimitive,
IntoPrimitive,
FromBytes,
IntoBytes,
Immutable,
KnownLayout,
Allocative,
)]
#[serde(rename_all = "lowercase")]
#[repr(u8)]
pub enum PoolId {
#[default]
Unknown,
BlockFills,
UltimusPool,
TerraPool,
Luxor,
OneThash,
BtcCom,
Bitfarms,
HuobiPool,
WayiCn,
CanoePool,
BtcTop,
BitcoinCom,
Pool175btc,
GbMiners,
AXbt,
AsicMiner,
BitMinter,
BitcoinRussia,
BtcServ,
SimplecoinUs,
BtcGuild,
Eligius,
OzCoin,
EclipseMc,
MaxBtc,
TripleMining,
CoinLab,
Pool50btc,
GhashIo,
StMiningCorp,
Bitparking,
Mmpool,
Polmine,
KncMiner,
Bitalo,
F2Pool,
Hhtt,
MegaBigPower,
MtRed,
NmcBit,
YourbtcNet,
GiveMeCoins,
BraiinsPool,
AntPool,
MultiCoinCo,
BcpoolIo,
Cointerra,
KanoPool,
SoloCk,
CkPool,
NiceHash,
BitClub,
BitcoinAffiliateNetwork,
Btcc,
BwPool,
ExxBw,
Bitsolo,
BitFury,
TwentyOneInc,
DigitalBtc,
EightBaochi,
MyBtcCoinPool,
TbDice,
HashPool,
Nexious,
BravoMining,
HotPool,
OkExPool,
BcMonster,
OneHash,
Bixin,
TatmasPool,
ViaBtc,
ConnectBtc,
BatPool,
Waterhole,
DcExploration,
Dcex,
BtPool,
FiftyEightCoin,
BitcoinIndia,
ShawnP0wers,
PHashIo,
RigPool,
HaoZhuZhu,
SevenPool,
MiningKings,
HashBx,
DPool,
Rawpool,
Haominer,
Helix,
BitcoinUkraine,
Poolin,
SecretSuperstar,
TigerpoolNet,
SigmapoolCom,
OkpoolTop,
Hummerpool,
Tangpool,
BytePool,
SpiderPool,
NovaBlock,
MiningCity,
BinancePool,
Minerium,
LubianCom,
Okkong,
AaoPool,
EmcdPool,
FoundryUsa,
SbiCrypto,
ArkPool,
PureBtcCom,
MaraPool,
KuCoinPool,
EntrustCharityPool,
OkMiner,
Titan,
PegaPool,
BtcNuggets,
CloudHashing,
DigitalXMintsy,
Telco214,
BtcPoolParty,
Multipool,
TransactionCoinMining,
BtcDig,
TrickysBtcPool,
BtcMp,
Eobot,
Unomp,
Patels,
GoGreenLight,
EkanemBtc,
Canoe,
Tiger,
OneM1x,
Zulupool,
SecPool,
Ocean,
WhitePool,
Wk057,
FutureBitApolloSolo,
CarbonNegative,
PortlandHodl,
Phoenix,
Neopool,
MaxiPool,
BitFuFuPool,
LuckyPool,
MiningDutch,
PublicPool,
MiningSquared,
InnopolisTech,
BtcLab,
Parasite,
Dummy158,
Dummy159,
Dummy160,
Dummy161,
Dummy162,
Dummy163,
Dummy164,
Dummy165,
Dummy166,
Dummy167,
Dummy168,
Dummy169,
Dummy170,
Dummy171,
Dummy172,
Dummy173,
Dummy174,
Dummy175,
Dummy176,
Dummy177,
Dummy178,
Dummy179,
Dummy180,
Dummy181,
Dummy182,
Dummy183,
Dummy184,
Dummy185,
Dummy186,
Dummy187,
Dummy188,
Dummy189,
Dummy190,
Dummy191,
Dummy192,
Dummy193,
Dummy194,
Dummy195,
Dummy196,
Dummy197,
Dummy198,
Dummy199,
Dummy200,
Dummy201,
Dummy202,
Dummy203,
Dummy204,
Dummy205,
Dummy206,
Dummy207,
Dummy208,
Dummy209,
Dummy210,
Dummy211,
Dummy212,
Dummy213,
Dummy214,
Dummy215,
Dummy216,
Dummy217,
Dummy218,
Dummy219,
Dummy220,
Dummy221,
Dummy222,
Dummy223,
Dummy224,
Dummy225,
Dummy226,
Dummy227,
Dummy228,
Dummy229,
Dummy230,
Dummy231,
Dummy232,
Dummy233,
Dummy234,
Dummy235,
Dummy236,
Dummy237,
Dummy238,
Dummy239,
Dummy240,
Dummy241,
Dummy242,
Dummy243,
Dummy244,
Dummy245,
Dummy246,
Dummy247,
Dummy248,
Dummy249,
Dummy250,
Dummy251,
Dummy252,
Dummy253,
Dummy254,
Dummy255,
}
+240
View File
@@ -0,0 +1,240 @@
use std::{collections::BTreeMap, path::Path};
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_store::AnyStore;
use brk_structs::{AddressBytes, Height, OutputIndex, OutputType};
use rayon::prelude::*;
use vecdb::{
AnyCollectableVec, AnyIterableVec, AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec,
PAGE_SIZE, RawVec, StoredIndex, VecIterator, Version,
};
mod id;
mod pool;
#[allow(clippy::module_inception)]
mod pools;
mod vecs;
pub use id::*;
pub use pool::*;
pub use pools::*;
use crate::{
chain,
indexes::{self, Indexes},
price,
};
#[derive(Clone, Allocative)]
pub struct Vecs {
db: Database,
pools: &'static Pools,
height_to_pool: RawVec<Height, PoolId>,
vecs: BTreeMap<PoolId, vecs::Vecs>,
}
impl Vecs {
pub fn forced_import(
parent_path: &Path,
parent_version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let db = Database::open(&parent_path.join("pools"))?;
db.set_min_len(PAGE_SIZE * 1_000_000)?;
let pools = pools();
let version = parent_version + Version::new(3) + Version::new(pools.len() as u64);
let this = Self {
height_to_pool: RawVec::forced_import(&db, "pool", version + Version::ZERO)?,
vecs: pools
.iter()
.map(|pool| {
vecs::Vecs::forced_import(
&db,
pool.id,
pools,
version + Version::ZERO,
indexes,
price,
)
.map(|vecs| (pool.id, vecs))
})
.collect::<Result<BTreeMap<_, _>>>()?,
pools,
db,
};
this.db.retain_regions(
this.vecs()
.into_iter()
.flat_map(|v| v.region_names())
.collect(),
)?;
Ok(this)
}
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
chain: &chain::Vecs,
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.compute_(indexer, indexes, starting_indexes, chain, price, exit)?;
self.db.flush_then_punch()?;
Ok(())
}
fn compute_(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
chain: &chain::Vecs,
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.compute_height_to_pool(indexer, indexes, starting_indexes, exit)?;
self.vecs.par_iter_mut().try_for_each(|(_, vecs)| {
vecs.compute(
indexer,
indexes,
starting_indexes,
&self.height_to_pool,
chain,
price,
exit,
)
})?;
Ok(())
}
fn compute_height_to_pool(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.height_to_pool.validate_computed_version_or_reset(
self.height_to_pool.version() + indexer.stores.height_to_coinbase_tag.version(),
)?;
let mut height_to_first_txindex_iter = indexer.vecs.height_to_first_txindex.iter();
let mut txindex_to_first_outputindex_iter =
indexer.vecs.txindex_to_first_outputindex.iter();
let mut txindex_to_output_count_iter = indexes.txindex_to_output_count.iter();
let mut outputindex_to_outputtype_iter = indexer.vecs.outputindex_to_outputtype.iter();
let mut outputindex_to_typeindex_iter = indexer.vecs.outputindex_to_typeindex.iter();
let mut p2pk65addressindex_to_p2pk65bytes_iter =
indexer.vecs.p2pk65addressindex_to_p2pk65bytes.iter();
let mut p2pk33addressindex_to_p2pk33bytes_iter =
indexer.vecs.p2pk33addressindex_to_p2pk33bytes.iter();
let mut p2pkhaddressindex_to_p2pkhbytes_iter =
indexer.vecs.p2pkhaddressindex_to_p2pkhbytes.iter();
let mut p2shaddressindex_to_p2shbytes_iter =
indexer.vecs.p2shaddressindex_to_p2shbytes.iter();
let mut p2wpkhaddressindex_to_p2wpkhbytes_iter =
indexer.vecs.p2wpkhaddressindex_to_p2wpkhbytes.iter();
let mut p2wshaddressindex_to_p2wshbytes_iter =
indexer.vecs.p2wshaddressindex_to_p2wshbytes.iter();
let mut p2traddressindex_to_p2trbytes_iter =
indexer.vecs.p2traddressindex_to_p2trbytes.iter();
let mut p2aaddressindex_to_p2abytes_iter = indexer.vecs.p2aaddressindex_to_p2abytes.iter();
let unknown = self.pools.get_unknown();
let min = starting_indexes
.height
.unwrap_to_usize()
.min(self.height_to_pool.len());
indexer
.stores
.height_to_coinbase_tag
.iter()
.skip(min)
.try_for_each(|(height, coinbase_tag)| -> Result<()> {
let txindex = height_to_first_txindex_iter.unwrap_get_inner(height);
let outputindex = txindex_to_first_outputindex_iter.unwrap_get_inner(txindex);
let outputcount = txindex_to_output_count_iter.unwrap_get_inner(txindex);
let pool = (*outputindex..(*outputindex + *outputcount))
.map(OutputIndex::from)
.find_map(|outputindex| {
let outputtype =
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
let typeindex = outputindex_to_typeindex_iter.unwrap_get_inner(outputindex);
let address = match outputtype {
OutputType::P2PK65 => Some(AddressBytes::from(
p2pk65addressindex_to_p2pk65bytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2PK33 => Some(AddressBytes::from(
p2pk33addressindex_to_p2pk33bytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2PKH => Some(AddressBytes::from(
p2pkhaddressindex_to_p2pkhbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2SH => Some(AddressBytes::from(
p2shaddressindex_to_p2shbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2WPKH => Some(AddressBytes::from(
p2wpkhaddressindex_to_p2wpkhbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2WSH => Some(AddressBytes::from(
p2wshaddressindex_to_p2wshbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2TR => Some(AddressBytes::from(
p2traddressindex_to_p2trbytes_iter
.unwrap_get_inner(typeindex.into()),
)),
OutputType::P2A => Some(AddressBytes::from(
p2aaddressindex_to_p2abytes_iter.unwrap_get_inner(typeindex.into()),
)),
_ => None,
};
address
.and_then(|address| self.pools.find_from_address(&address.to_string()))
})
.or_else(|| self.pools.find_from_coinbase_tag(&coinbase_tag))
.unwrap_or(unknown);
self.height_to_pool.push_if_needed(height, pool.id)?;
Ok(())
})?;
self.height_to_pool.safe_flush(exit)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.vecs
.iter()
.flat_map(|(_, vecs)| vecs.vecs())
.collect::<Vec<_>>(),
vec![&self.height_to_pool],
]
.into_iter()
.flatten()
.collect::<Vec<_>>()
}
}
+46
View File
@@ -0,0 +1,46 @@
use allocative::Allocative;
use crate::pools::PoolId;
#[derive(Debug, Allocative)]
pub struct Pool {
pub id: PoolId,
pub name: &'static str,
pub addresses: Box<[&'static str]>,
pub tags: Box<[&'static str]>,
pub tags_lowercase: Box<[String]>,
pub link: &'static str,
}
impl Pool {
pub fn serialized_id(&self) -> String {
let value = serde_json::to_value(self.id).unwrap();
value.as_str().unwrap().to_string()
}
}
impl From<(usize, JSONPool)> for Pool {
fn from((index, pool): (usize, JSONPool)) -> Self {
Self {
id: (index as u8).into(),
name: pool.name,
addresses: pool.addresses,
tags_lowercase: pool
.tags
.iter()
.map(|t| t.to_lowercase())
.collect::<Vec<_>>()
.into_boxed_slice(),
tags: pool.tags,
link: pool.link,
}
}
}
#[derive(Debug)]
pub struct JSONPool {
pub name: &'static str,
pub addresses: Box<[&'static str]>,
pub tags: Box<[&'static str]>,
pub link: &'static str,
}
File diff suppressed because it is too large Load Diff
+467
View File
@@ -0,0 +1,467 @@
use allocative::Allocative;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{Height, Sats, StoredF32, StoredU16, StoredU32};
use vecdb::{AnyCollectableVec, AnyIterableVec, Database, Exit, StoredIndex, VecIterator, Version};
use crate::{
PoolId, Pools, chain,
grouped::{
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source,
VecBuilderOptions,
},
indexes::{self, Indexes},
price,
};
#[derive(Clone, Allocative)]
pub struct Vecs {
id: PoolId,
indexes_to_blocks_mined: ComputedVecsFromHeight<StoredU32>,
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
indexes_to_subsidy: ComputedValueVecsFromHeight,
indexes_to_fee: ComputedValueVecsFromHeight,
indexes_to_coinbase: ComputedValueVecsFromHeight,
indexes_to_dominance: ComputedVecsFromDateIndex<StoredF32>,
indexes_to_1d_dominance: ComputedVecsFromDateIndex<StoredF32>,
indexes_to_1w_dominance: ComputedVecsFromDateIndex<StoredF32>,
indexes_to_1m_dominance: ComputedVecsFromDateIndex<StoredF32>,
indexes_to_1y_dominance: ComputedVecsFromDateIndex<StoredF32>,
indexes_to_days_since_block: ComputedVecsFromDateIndex<StoredU16>,
}
impl Vecs {
pub fn forced_import(
db: &Database,
id: PoolId,
pools: &Pools,
parent_version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let pool = pools.get(id);
let name = pool.serialized_id();
let suffix = |s: &str| format!("{name}_{s}");
let compute_dollars = price.is_some();
let version = parent_version + Version::ZERO;
Ok(Self {
id,
indexes_to_blocks_mined: ComputedVecsFromHeight::forced_import(
db,
&suffix("blocks_mined"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1w_blocks_mined"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1m_blocks_mined"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1y_blocks_mined"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_subsidy: ComputedValueVecsFromHeight::forced_import(
db,
&suffix("subsidy"),
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default().add_sum().add_cumulative(),
compute_dollars,
indexes,
)?,
indexes_to_fee: ComputedValueVecsFromHeight::forced_import(
db,
&suffix("fee"),
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default().add_sum().add_cumulative(),
compute_dollars,
indexes,
)?,
indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import(
db,
&suffix("coinbase"),
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default().add_sum().add_cumulative(),
compute_dollars,
indexes,
)?,
indexes_to_dominance: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("dominance"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1d_dominance: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1d_dominance"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1w_dominance: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1w_dominance"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1m_dominance: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1m_dominance"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_1y_dominance: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("1y_dominance"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_days_since_block: ComputedVecsFromDateIndex::forced_import(
db,
&suffix("days_since_block"),
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
})
}
#[allow(clippy::too_many_arguments)]
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
height_to_pool: &impl AnyIterableVec<Height, PoolId>,
chain: &chain::Vecs,
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.indexes_to_blocks_mined.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_transform(
starting_indexes.height,
height_to_pool,
|(h, id, ..)| {
(
h,
if id == self.id {
StoredU32::ONE
} else {
StoredU32::ZERO
},
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1w_blocks_mined.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
7,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1m_blocks_mined.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
30,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1y_blocks_mined.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
365,
exit,
)?;
Ok(())
},
)?;
let height_to_blocks_mined = self.indexes_to_blocks_mined.height.as_ref().unwrap();
self.indexes_to_subsidy.compute_all(
indexer,
indexes,
price,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_transform2(
starting_indexes.height,
height_to_blocks_mined,
chain.indexes_to_subsidy.sats.height.as_ref().unwrap(),
|(h, mined, sats, ..)| {
(
h,
if mined == StoredU32::ONE {
sats
} else {
Sats::ZERO
},
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_fee.compute_all(
indexer,
indexes,
price,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_transform2(
starting_indexes.height,
height_to_blocks_mined,
chain.indexes_to_fee.sats.height.unwrap_sum(),
|(h, mined, sats, ..)| {
(
h,
if mined == StoredU32::ONE {
sats
} else {
Sats::ZERO
},
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_coinbase.compute_all(
indexer,
indexes,
price,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_transform2(
starting_indexes.height,
height_to_blocks_mined,
chain.indexes_to_coinbase.sats.height.as_ref().unwrap(),
|(h, mined, sats, ..)| {
(
h,
if mined == StoredU32::ONE {
sats
} else {
Sats::ZERO
},
)
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_dominance.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_blocks_mined.dateindex.unwrap_cumulative(),
chain.indexes_to_block_count.dateindex.unwrap_cumulative(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1d_dominance.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
chain.indexes_to_block_count.dateindex.unwrap_sum(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1w_dominance.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_1w_blocks_mined.dateindex.as_ref().unwrap(),
chain.indexes_to_1w_block_count.dateindex.as_ref().unwrap(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1m_dominance.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_1m_blocks_mined.dateindex.as_ref().unwrap(),
chain.indexes_to_1m_block_count.dateindex.as_ref().unwrap(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_1y_dominance.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_1y_blocks_mined.dateindex.as_ref().unwrap(),
chain.indexes_to_1y_block_count.dateindex.as_ref().unwrap(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_days_since_block.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
let mut prev = None;
v.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
self.indexes_to_blocks_mined.dateindex.unwrap_cumulative(),
|(i, sum, cumulative, slf)| {
if prev.is_none() {
let i = i.unwrap_to_usize();
prev.replace(if i > 0 {
slf.into_iter().unwrap_get_inner_(i - 1)
} else {
StoredU16::ZERO
});
}
let days = if !cumulative.is_zero() && sum.is_zero() {
prev.unwrap() + StoredU16::ONE
} else {
StoredU16::ZERO
};
prev.replace(days);
(i, days)
},
exit,
)?;
Ok(())
},
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.indexes_to_blocks_mined.vecs(),
self.indexes_to_1w_blocks_mined.vecs(),
self.indexes_to_1m_blocks_mined.vecs(),
self.indexes_to_1y_blocks_mined.vecs(),
self.indexes_to_subsidy.vecs(),
self.indexes_to_fee.vecs(),
self.indexes_to_coinbase.vecs(),
self.indexes_to_dominance.vecs(),
self.indexes_to_1d_dominance.vecs(),
self.indexes_to_1w_dominance.vecs(),
self.indexes_to_1m_dominance.vecs(),
self.indexes_to_1y_dominance.vecs(),
self.indexes_to_days_since_block.vecs(),
]
.into_iter()
.flatten()
.collect()
}
}
+121 -59
View File
@@ -77,8 +77,10 @@ pub struct Vecs {
pub indexes_to_value_destroyed: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_unrealized_profit: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_unrealized_total_pnl: Option<EagerVec<Height, Dollars>>,
pub indexes_to_unrealized_total_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_total_unrealized_pnl: Option<EagerVec<Height, Dollars>>,
pub indexes_to_total_unrealized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_total_realized_pnl: Option<EagerVec<Height, Dollars>>,
pub indexes_to_total_realized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_min_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_max_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub height_to_supply_half_value: ComputedHeightValueVecs,
@@ -110,21 +112,21 @@ pub struct Vecs {
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub height_to_unrealized_profit_rel_to_own_unrealized_total_pnl:
pub height_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub height_to_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub height_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl:
pub height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<EagerVec<Height, StoredF32>>,
pub indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl:
pub indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl:
pub indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl:
pub indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_realized_cap_rel_to_own_market_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_realized_profit_rel_to_realized_cap: Option<ComputedVecsFromHeight<StoredF32>>,
@@ -370,18 +372,18 @@ impl Vecs {
)
.unwrap()
}),
height_to_unrealized_total_pnl: compute_dollars.then(|| {
height_to_total_unrealized_pnl: compute_dollars.then(|| {
EagerVec::forced_import_compressed(
db,
&suffix("unrealized_total_pnl"),
&suffix("total_unrealized_pnl"),
version + VERSION + Version::ZERO,
)
.unwrap()
}),
indexes_to_unrealized_total_pnl: compute_dollars.then(|| {
indexes_to_total_unrealized_pnl: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_total_pnl"),
&suffix("total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ZERO,
indexes,
@@ -389,6 +391,25 @@ impl Vecs {
)
.unwrap()
}),
height_to_total_realized_pnl: compute_dollars.then(|| {
EagerVec::forced_import_compressed(
db,
&suffix("total_realized_pnl"),
version + VERSION + Version::ZERO,
)
.unwrap()
}),
indexes_to_total_realized_pnl: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("total_realized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
VecBuilderOptions::default().add_sum(),
)
.unwrap()
}),
dateindex_to_unrealized_loss,
height_to_realized_cap: compute_dollars.then(|| {
EagerVec::forced_import(
@@ -990,56 +1011,56 @@ impl Vecs {
)
.unwrap()
}),
height_to_unrealized_profit_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("unrealized_profit_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_profit_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ZERO,
format,
)
.unwrap()
}),
height_to_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_loss_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ZERO,
format,
)
.unwrap()
}),
height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("neg_unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ZERO,
format,
)
.unwrap()
}),
height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl: (compute_dollars
height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
EagerVec::forced_import(
db,
&suffix("net_unrealized_pnl_rel_to_own_unrealized_total_pnl"),
&suffix("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
version + VERSION + Version::ONE,
format,
)
.unwrap()
}),
indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_profit_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_profit_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -1047,12 +1068,12 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("unrealized_loss_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -1060,12 +1081,12 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("neg_unrealized_loss_rel_to_own_unrealized_total_pnl"),
&suffix("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -1073,12 +1094,12 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl: (compute_dollars
indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars
&& extended)
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("net_unrealized_pnl_rel_to_own_unrealized_total_pnl"),
&suffix("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
Source::Compute,
version + VERSION + Version::ONE,
indexes,
@@ -2673,7 +2694,7 @@ impl Vecs {
exit,
Some(self.dateindex_to_unrealized_loss.as_ref().unwrap()),
)?;
self.height_to_unrealized_total_pnl
self.height_to_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_add(
@@ -2682,7 +2703,7 @@ impl Vecs {
self.height_to_unrealized_loss.as_ref().unwrap(),
exit,
)?;
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -2700,6 +2721,41 @@ impl Vecs {
Ok(())
},
)?;
self.height_to_total_realized_pnl
.as_mut()
.unwrap()
.compute_add(
starting_indexes.height,
self.height_to_realized_profit.as_ref().unwrap(),
self.height_to_realized_loss.as_ref().unwrap(),
exit,
)?;
self.indexes_to_total_realized_pnl
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_add(
starting_indexes.dateindex,
self.indexes_to_realized_profit
.as_ref()
.unwrap()
.dateindex
.unwrap_sum(),
self.indexes_to_realized_loss
.as_ref()
.unwrap()
.dateindex
.unwrap_sum(),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_min_price_paid
.as_mut()
@@ -3043,46 +3099,46 @@ impl Vecs {
}
if self
.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.is_some()
{
self.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_profit.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.height_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_loss.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_neg_unrealized_loss.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_net_unrealized_pnl.as_ref().unwrap(),
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
exit,
)?;
self.indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3094,7 +3150,7 @@ impl Vecs {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.as_ref().unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3105,7 +3161,7 @@ impl Vecs {
Ok(())
},
)?;
self.indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3117,7 +3173,7 @@ impl Vecs {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_loss.as_ref().unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3128,7 +3184,7 @@ impl Vecs {
Ok(())
},
)?;
self.indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3145,7 +3201,7 @@ impl Vecs {
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3156,7 +3212,7 @@ impl Vecs {
Ok(())
},
)?;
self.indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_mut()
.unwrap()
.compute_all(
@@ -3173,7 +3229,7 @@ impl Vecs {
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
@@ -3806,10 +3862,16 @@ impl Vecs {
self.indexes_to_unrealized_loss
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_unrealized_total_pnl
self.height_to_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.indexes_to_unrealized_total_pnl
self.indexes_to_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_total_realized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.indexes_to_total_realized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_min_price_paid
@@ -3843,28 +3905,28 @@ impl Vecs {
self.indexes_to_net_unrealized_pnl_rel_to_own_market_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.height_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| vec![v]),
self.indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.height_to_neg_unrealized_loss
+3 -3
View File
@@ -14,7 +14,7 @@ pub struct BRK {
dateindex_to_ohlc: BTreeMap<DateIndex, Vec<OHLCCents>>,
}
const API_URL: &str = "https://bitcoinresearchkit.org/api/vecs";
const API_URL: &str = "https://bitview.space/api/vecs";
const CHUNK_SIZE: usize = 10_000;
impl BRK {
@@ -46,7 +46,7 @@ impl BRK {
default_retry(|_| {
let url = format!(
"{API_URL}/height-to-ohlc?from={}&to={}",
"{API_URL}/height-to-price-ohlc?from={}&to={}",
height,
height + CHUNK_SIZE
);
@@ -91,7 +91,7 @@ impl BRK {
default_retry(|_| {
let url = format!(
"{API_URL}/dateindex-to-ohlc?from={}&to={}",
"{API_URL}/dateindex-to-price-ohlc?from={}&to={}",
dateindex,
dateindex + CHUNK_SIZE
);
+6 -3
View File
@@ -23,9 +23,12 @@ pub use indexes::*;
pub use stores::*;
pub use vecs::*;
// One version for all data sources
// Increment on change OR addition
const VERSION: Version = Version::new(21);
const SNAPSHOT_BLOCK_RANGE: usize = 1_000;
const COLLISIONS_CHECKED_UP_TO: Height = Height::new(909_150);
const VERSION: Version = Version::ONE;
#[derive(Clone)]
pub struct Indexer {
@@ -39,10 +42,10 @@ impl Indexer {
let path = outputs_dir.join("indexed");
let vecs = Vecs::forced_import(&path, VERSION + Version::ZERO)?;
let vecs = Vecs::forced_import(&path, VERSION)?;
info!("Imported vecs");
let stores = Stores::forced_import(&path, VERSION + Version::ZERO)?;
let stores = Stores::forced_import(&path, VERSION)?;
info!("Imported stores");
Ok(Self { vecs, stores })
+14 -34
View File
@@ -27,8 +27,6 @@ pub struct Stores {
ByAddressType<Store<TypeIndexWithOutputindex, Unit>>,
}
const VERSION: Version = Version::ZERO;
impl Stores {
pub fn forced_import(parent: &Path, version: Version) -> Result<Self> {
let path = parent.join("stores");
@@ -49,34 +47,21 @@ impl Stores {
&keyspace,
&path,
"addressbyteshash_to_typeindex",
version + VERSION + Version::ZERO,
version,
None,
)
});
let blockhashprefix_to_height = scope.spawn(|| {
Store::import(
&keyspace,
&path,
"blockhashprefix_to_height",
version + VERSION + Version::ZERO,
None,
)
});
let txidprefix_to_txindex = scope.spawn(|| {
Store::import(
&keyspace,
&path,
"txidprefix_to_txindex",
version + VERSION + Version::ZERO,
None,
)
Store::import(&keyspace, &path, "blockhashprefix_to_height", version, None)
});
let txidprefix_to_txindex = scope
.spawn(|| Store::import(&keyspace, &path, "txidprefix_to_txindex", version, None));
let p2aaddressindex_with_outputindex = scope.spawn(|| {
Store::import(
&keyspace,
&path,
"p2aaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -85,7 +70,7 @@ impl Stores {
&keyspace,
&path,
"p2pk33addressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -94,7 +79,7 @@ impl Stores {
&keyspace,
&path,
"p2pk65addressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -103,7 +88,7 @@ impl Stores {
&keyspace,
&path,
"p2pkhaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -112,7 +97,7 @@ impl Stores {
&keyspace,
&path,
"p2shaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -121,7 +106,7 @@ impl Stores {
&keyspace,
&path,
"p2traddressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -130,7 +115,7 @@ impl Stores {
&keyspace,
&path,
"p2wpkhaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
@@ -139,18 +124,13 @@ impl Stores {
&keyspace,
&path,
"p2wshaddressindex_with_outputindex",
version + VERSION + Version::ZERO,
version,
Some(false),
)
});
let height_to_coinbase_tag = Store::import(
&keyspace,
&path,
"height_to_coinbase_tag",
version + VERSION + Version::ZERO,
None,
)?;
let height_to_coinbase_tag =
Store::import(&keyspace, &path, "height_to_coinbase_tag", version, None)?;
Ok(Self {
keyspace: keyspace.clone(),
+44 -150
View File
@@ -17,8 +17,6 @@ use vecdb::{
use crate::Indexes;
const VERSION: Version = Version::ZERO;
#[derive(Clone)]
pub struct Vecs {
db: Database,
@@ -78,222 +76,118 @@ impl Vecs {
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let this = Self {
emptyoutputindex_to_txindex: CompressedVec::forced_import(
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
height_to_blockhash: RawVec::forced_import(
&db,
"blockhash",
version + VERSION + Version::ZERO,
)?,
height_to_difficulty: CompressedVec::forced_import(
&db,
"difficulty",
version + VERSION + Version::ZERO,
)?,
emptyoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
height_to_blockhash: RawVec::forced_import(&db, "blockhash", version)?,
height_to_difficulty: CompressedVec::forced_import(&db, "difficulty", version)?,
height_to_first_emptyoutputindex: CompressedVec::forced_import(
&db,
"first_emptyoutputindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_inputindex: CompressedVec::forced_import(
&db,
"first_inputindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_opreturnindex: CompressedVec::forced_import(
&db,
"first_opreturnindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_outputindex: CompressedVec::forced_import(
&db,
"first_outputindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2aaddressindex: CompressedVec::forced_import(
&db,
"first_p2aaddressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2msoutputindex: CompressedVec::forced_import(
&db,
"first_p2msoutputindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2pk33addressindex: CompressedVec::forced_import(
&db,
"first_p2pk33addressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2pk65addressindex: CompressedVec::forced_import(
&db,
"first_p2pk65addressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2pkhaddressindex: CompressedVec::forced_import(
&db,
"first_p2pkhaddressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2shaddressindex: CompressedVec::forced_import(
&db,
"first_p2shaddressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2traddressindex: CompressedVec::forced_import(
&db,
"first_p2traddressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2wpkhaddressindex: CompressedVec::forced_import(
&db,
"first_p2wpkhaddressindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_p2wshaddressindex: CompressedVec::forced_import(
&db,
"first_p2wshaddressindex",
version + VERSION + Version::ZERO,
)?,
height_to_first_txindex: CompressedVec::forced_import(
&db,
"first_txindex",
version + VERSION + Version::ZERO,
version,
)?,
height_to_first_txindex: CompressedVec::forced_import(&db, "first_txindex", version)?,
height_to_first_unknownoutputindex: CompressedVec::forced_import(
&db,
"first_unknownoutputindex",
version + VERSION + Version::ZERO,
)?,
height_to_timestamp: CompressedVec::forced_import(
&db,
"timestamp",
version + VERSION + Version::ZERO,
)?,
height_to_total_size: CompressedVec::forced_import(
&db,
"total_size",
version + VERSION + Version::ZERO,
)?,
height_to_weight: CompressedVec::forced_import(
&db,
"weight",
version + VERSION + Version::ZERO,
)?,
inputindex_to_outputindex: RawVec::forced_import(
&db,
"outputindex",
version + VERSION + Version::ZERO,
)?,
opreturnindex_to_txindex: CompressedVec::forced_import(
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
outputindex_to_outputtype: RawVec::forced_import(
&db,
"outputtype",
version + VERSION + Version::ZERO,
)?,
outputindex_to_typeindex: RawVec::forced_import(
&db,
"typeindex",
version + VERSION + Version::ZERO,
)?,
outputindex_to_value: RawVec::forced_import(
&db,
"value",
version + VERSION + Version::ZERO,
)?,
p2aaddressindex_to_p2abytes: RawVec::forced_import(
&db,
"p2abytes",
version + VERSION + Version::ZERO,
)?,
p2msoutputindex_to_txindex: CompressedVec::forced_import(
&db,
"txindex",
version + VERSION + Version::ZERO,
)?,
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(
&db,
"p2pk33bytes",
version + VERSION + Version::ZERO,
)?,
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(
&db,
"p2pk65bytes",
version + VERSION + Version::ZERO,
)?,
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(
&db,
"p2pkhbytes",
version + VERSION + Version::ZERO,
)?,
p2shaddressindex_to_p2shbytes: RawVec::forced_import(
&db,
"p2shbytes",
version + VERSION + Version::ZERO,
)?,
p2traddressindex_to_p2trbytes: RawVec::forced_import(
&db,
"p2trbytes",
version + VERSION + Version::ZERO,
)?,
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(
&db,
"p2wpkhbytes",
version + VERSION + Version::ZERO,
)?,
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(
&db,
"p2wshbytes",
version + VERSION + Version::ZERO,
)?,
txindex_to_base_size: CompressedVec::forced_import(
&db,
"base_size",
version + VERSION + Version::ZERO,
version,
)?,
height_to_timestamp: CompressedVec::forced_import(&db, "timestamp", version)?,
height_to_total_size: CompressedVec::forced_import(&db, "total_size", version)?,
height_to_weight: CompressedVec::forced_import(&db, "weight", version)?,
inputindex_to_outputindex: RawVec::forced_import(&db, "outputindex", version)?,
opreturnindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
outputindex_to_outputtype: RawVec::forced_import(&db, "outputtype", version)?,
outputindex_to_typeindex: RawVec::forced_import(&db, "typeindex", version)?,
outputindex_to_value: RawVec::forced_import(&db, "value", version)?,
p2aaddressindex_to_p2abytes: RawVec::forced_import(&db, "p2abytes", version)?,
p2msoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(&db, "p2pk33bytes", version)?,
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(&db, "p2pk65bytes", version)?,
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(&db, "p2pkhbytes", version)?,
p2shaddressindex_to_p2shbytes: RawVec::forced_import(&db, "p2shbytes", version)?,
p2traddressindex_to_p2trbytes: RawVec::forced_import(&db, "p2trbytes", version)?,
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(&db, "p2wpkhbytes", version)?,
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(&db, "p2wshbytes", version)?,
txindex_to_base_size: CompressedVec::forced_import(&db, "base_size", version)?,
txindex_to_first_inputindex: CompressedVec::forced_import(
&db,
"first_inputindex",
version + VERSION + Version::ZERO,
version,
)?,
txindex_to_first_outputindex: CompressedVec::forced_import(
&db,
"first_outputindex",
version + VERSION + Version::ZERO,
version,
)?,
txindex_to_is_explicitly_rbf: CompressedVec::forced_import(
&db,
"is_explicitly_rbf",
version + VERSION + Version::ZERO,
)?,
txindex_to_rawlocktime: CompressedVec::forced_import(
&db,
"rawlocktime",
version + VERSION + Version::ZERO,
)?,
txindex_to_total_size: CompressedVec::forced_import(
&db,
"total_size",
version + VERSION + Version::ZERO,
)?,
txindex_to_txid: RawVec::forced_import(&db, "txid", version + VERSION + Version::ZERO)?,
txindex_to_txversion: CompressedVec::forced_import(
&db,
"txversion",
version + VERSION + Version::ZERO,
)?,
unknownoutputindex_to_txindex: CompressedVec::forced_import(
&db,
"txindex",
version + VERSION + Version::ZERO,
version,
)?,
txindex_to_rawlocktime: CompressedVec::forced_import(&db, "rawlocktime", version)?,
txindex_to_total_size: CompressedVec::forced_import(&db, "total_size", version)?,
txindex_to_txid: RawVec::forced_import(&db, "txid", version)?,
txindex_to_txversion: CompressedVec::forced_import(&db, "txversion", version)?,
unknownoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
db,
};
+1
View File
@@ -16,6 +16,7 @@ brk_indexer = { workspace = true }
brk_structs = { workspace = true }
vecdb = { workspace = true }
derive_deref = { workspace = true }
quick_cache = { workspace = true }
schemars = "1.0.4"
serde = { workspace = true }
serde_json = { workspace = true }
+1
View File
@@ -4,6 +4,7 @@ use serde::Deserialize;
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum Format {
#[serde(alias = "json")]
JSON,
+84
View File
@@ -0,0 +1,84 @@
use std::fmt;
use derive_deref::Deref;
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Debug, Deref, JsonSchema)]
pub struct MaybeIds(Vec<String>);
const MAX_STRING_SIZE: usize = 10_000;
const MAX_VECS: usize = 64;
impl From<String> for MaybeIds {
fn from(value: String) -> Self {
Self(vec![value])
}
}
impl<'a> From<Vec<&'a str>> for MaybeIds {
fn from(value: Vec<&'a str>) -> Self {
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
}
}
impl<'de> Deserialize<'de> for MaybeIds {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
match serde_json::Value::deserialize(deserializer)? {
serde_json::Value::String(str) => {
if str.len() <= MAX_STRING_SIZE {
Ok(MaybeIds(sanitize_ids(
str.split(",").map(|s| s.to_string()),
)))
} else {
dbg!(str.len(), MAX_STRING_SIZE);
Err(serde::de::Error::custom("Given parameter is too long"))
}
}
serde_json::Value::Array(vec) => {
if vec.len() <= MAX_VECS {
Ok(MaybeIds(sanitize_ids(
vec.into_iter().map(|s| s.as_str().unwrap().to_string()),
)))
} else {
dbg!(vec.len(), MAX_VECS);
Err(serde::de::Error::custom("Given parameter is too long"))
}
}
_ => Err(serde::de::Error::custom("Bad ids format")),
}
}
}
impl fmt::Display for MaybeIds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = self.0.join(",");
write!(f, "{s}")
}
}
fn sanitize_ids(raw_ids: impl Iterator<Item = String>) -> Vec<String> {
let mut results = Vec::new();
raw_ids.for_each(|s| {
let mut current = String::new();
for c in s.to_lowercase().chars() {
match c {
' ' | ',' | '+' => {
if !current.is_empty() {
results.push(std::mem::take(&mut current));
}
}
'-' => current.push('_'),
c if c.is_alphanumeric() || c == '_' => current.push(c),
_ => {}
}
}
if !current.is_empty() {
results.push(current);
}
});
results
}
+1
View File
@@ -12,6 +12,7 @@ use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum Index {
#[schemars(description = "Date/day index")]
DateIndex,
+24 -19
View File
@@ -1,6 +1,6 @@
#![doc = include_str!("../README.md")]
use std::collections::BTreeMap;
use std::{collections::BTreeMap, sync::OnceLock};
use brk_computer::Computer;
use brk_error::{Error, Result};
@@ -10,13 +10,14 @@ use nucleo_matcher::{
Config, Matcher,
pattern::{AtomKind, CaseMatching, Normalization, Pattern},
};
use quick_cache::sync::Cache;
use tabled::settings::Style;
use vecdb::{AnyCollectableVec, AnyStoredVec};
mod deser;
mod format;
mod ids;
mod index;
mod maybe_ids;
mod output;
mod pagination;
mod params;
@@ -33,6 +34,11 @@ use vecs::Vecs;
use crate::vecs::{IdToVec, IndexToVec};
pub fn cached_errors() -> &'static Cache<String, String> {
static CACHE: OnceLock<Cache<String, String>> = OnceLock::new();
CACHE.get_or_init(|| Cache::new(1000))
}
#[allow(dead_code)]
pub struct Interface<'a> {
vecs: Vecs<'a>,
@@ -58,34 +64,31 @@ impl<'a> Interface<'a> {
}
pub fn search(&self, params: &Params) -> Result<Vec<(String, &&dyn AnyCollectableVec)>> {
let ids = &params.ids;
let index = params.index;
let ids_to_vec = self
.vecs
.index_to_id_to_vec
.get(&params.index)
.get(&index)
.ok_or(Error::String(format!(
"Index \"{}\" isn't a valid index",
params.index
index
)))?;
let maybe_ids = params.ids.iter().flat_map(|s| {
s.to_lowercase()
.replace("-", "_")
.split_whitespace()
.flat_map(|s| {
s.split(',')
.flat_map(|s| s.split('+').map(|s| s.to_string()))
})
.collect::<Vec<_>>()
});
maybe_ids
ids.iter()
.map(|id| {
let vec = ids_to_vec.get(id.as_str()).ok_or_else(|| {
let cached_errors = cached_errors();
if let Some(message) = cached_errors.get(id) {
return Error::String(message)
}
let mut message = format!(
"No vec named \"{}\" indexed by \"{}\" found.\n",
// tell if id found in another index
id,
params.index
index
);
let mut matcher = Matcher::new(Config::DEFAULT);
@@ -111,9 +114,11 @@ impl<'a> Interface<'a> {
message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys());
}
cached_errors.insert(id.clone(), message.clone());
Error::String(message)
});
vec.map(|vec| (id, vec))
vec.map(|vec| (id.clone(), vec))
})
.collect::<Result<Vec<_>>>()
}
-38
View File
@@ -1,38 +0,0 @@
use derive_deref::Deref;
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Debug, Deref, JsonSchema)]
pub struct MaybeIds(Vec<String>);
impl From<String> for MaybeIds {
fn from(value: String) -> Self {
Self(vec![value])
}
}
impl<'a> From<Vec<&'a str>> for MaybeIds {
fn from(value: Vec<&'a str>) -> Self {
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
}
}
impl<'de> Deserialize<'de> for MaybeIds {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let maybe_ids = match serde_json::Value::deserialize(deserializer)? {
serde_json::Value::String(str) => {
str.split(",").map(|s| s.to_string()).collect::<Vec<_>>()
}
serde_json::Value::Array(vec) => vec
.into_iter()
.map(|s| s.as_str().unwrap().to_string())
.collect::<Vec<_>>(),
_ => return Err(serde::de::Error::custom("Bad ids format")),
};
// dbg!(&maybe_ids);
Ok(MaybeIds(maybe_ids))
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ use tabled::Tabled as TabledTabled;
use crate::Format;
#[derive(Debug, Serialize)]
#[serde(untagged)]
#[serde(untagged, rename_all = "lowercase")]
pub enum Output {
Json(Value),
CSV(String),
+1 -1
View File
@@ -6,7 +6,7 @@ use serde::Deserialize;
use crate::{
Format, Index,
deser::{de_unquote_i64, de_unquote_usize},
maybe_ids::MaybeIds,
ids::MaybeIds,
};
#[derive(Debug, Deserialize, JsonSchema)]
+15 -44
View File
@@ -1,7 +1,7 @@
use std::path::Path;
use bitcoincore_rpc::{Auth, Client, Result};
use brk_parser::Parser;
use brk_parser::{BlockExtended, Parser};
use brk_structs::Height;
#[allow(clippy::needless_doctest_main)]
@@ -21,55 +21,26 @@ fn main() -> Result<()> {
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir), rpc);
let start = None;
let end = None;
parser
.parse(start, end)
.iter()
.for_each(|(height, _block, hash)| {
println!("{height}: {}", hash);
});
// let start = None;
// let end = None;
// parser
// .parse(start, end)
// .iter()
// .for_each(|(height, _block, hash)| {
// println!("{height}: {}", hash);
// });
let block_0 = parser.get(Height::new(0));
println!(
"{}",
block_0
.txdata
.first()
.unwrap()
.output
.first()
.unwrap()
.script_pubkey
);
dbg!("{}", block_0.coinbase_tag());
let block_158251 = parser.get(Height::new(158251));
println!(
"{}",
block_158251
.txdata
.first()
.unwrap()
.output
.first()
.unwrap()
.script_pubkey
);
dbg!("{}", block_158251.coinbase_tag());
let block_173195 = parser.get(Height::new(173195));
dbg!("{}", block_173195.coinbase_tag());
let block_840_000 = parser.get(Height::new(840_004));
println!(
"{}",
block_840_000
.txdata
.first()
.unwrap()
.output
.first()
.unwrap()
.value
);
dbg!("{}", block_840_000.coinbase_tag());
dbg!(i.elapsed());
+12 -11
View File
@@ -1,19 +1,20 @@
use std::borrow::Cow;
use bitcoin::Block;
pub trait BlockExtended {
fn coinbase_tag(&self) -> String;
fn coinbase_tag(&self) -> Cow<'_, str>;
}
impl BlockExtended for Block {
fn coinbase_tag(&self) -> String {
let Some(input) = self.txdata.first().and_then(|tx| tx.input.first()) else {
return String::new();
};
let bytes = input.script_sig.as_bytes();
String::from_utf8_lossy(bytes)
.chars()
.filter(|&c| c != '\u{FFFD}' && (c >= ' ' || c == '\n' || c == '\r' || c == '\t'))
.take(1_024)
.collect()
fn coinbase_tag(&self) -> Cow<'_, str> {
String::from_utf8_lossy(
self.txdata
.first()
.and_then(|tx| tx.input.first())
.unwrap()
.script_sig
.as_bytes(),
)
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ brk_parser = { workspace = true }
vecdb = { workspace = true }
jiff = { workspace = true }
log = { workspace = true }
quick_cache = "0.6.16"
quick_cache = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
tower-http = { version = "0.6.6", features = ["compression-full", "trace"] }
-7
View File
@@ -3,18 +3,11 @@ use brk_structs::{Height, Version};
pub trait AnyStore {
fn commit(&mut self, height: Height) -> Result<()>;
fn persist(&self) -> Result<()>;
fn reset(&mut self) -> Result<()>;
fn name(&self) -> &'static str;
fn height(&self) -> Option<Height>;
fn has(&self, height: Height) -> bool;
fn needs(&self, height: Height) -> bool;
fn version(&self) -> Version;
}
+6 -6
View File
@@ -126,12 +126,12 @@ where
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v)))))
// }
// pub fn tx_iter(&self) -> impl Iterator<Item = (K, V)> {
// self.rtx
// .iter(&self.partition.load())
// .map(|res| res.unwrap())
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
// }
pub fn iter(&self) -> impl Iterator<Item = (K, V)> {
self.rtx
.iter(self.partition.as_ref().unwrap())
.map(|res| res.unwrap())
.map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
}
pub fn insert_if_needed(&mut self, key: K, value: V, height: Height) {
if self.needs(height) {
+2
View File
@@ -10,6 +10,8 @@ rust-version.workspace = true
build = "build.rs"
[dependencies]
allocative = { workspace = true }
allocative_derive = { workspace = true }
bitcoin = { workspace = true }
bitcoincore-rpc = { workspace = true }
brk_error = {workspace = true}
@@ -25,6 +25,25 @@ pub enum AddressBytes {
P2A(P2ABytes),
}
impl fmt::Display for AddressBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
AddressBytes::P2PK65(bytes) => bytes.to_string(),
AddressBytes::P2PK33(bytes) => bytes.to_string(),
AddressBytes::P2PKH(bytes) => bytes.to_string(),
AddressBytes::P2SH(bytes) => bytes.to_string(),
AddressBytes::P2WPKH(bytes) => bytes.to_string(),
AddressBytes::P2WSH(bytes) => bytes.to_string(),
AddressBytes::P2TR(bytes) => bytes.to_string(),
AddressBytes::P2A(bytes) => bytes.to_string(),
}
)
}
}
impl AddressBytes {
pub fn as_slice(&self) -> &[u8] {
match self {
@@ -44,6 +44,7 @@ impl Serialize for AnyAddressIndex {
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum AnyAddressDataIndexEnum {
Loaded(LoadedAddressIndex),
Empty(EmptyAddressIndex),
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div, Mul},
};
use allocative::Allocative;
use serde::Serialize;
use vecdb::{CheckedSub, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -20,6 +21,7 @@ use super::{Sats, StoredF64};
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct Bitcoin(f64);
+3 -1
View File
@@ -3,10 +3,11 @@ use std::{
ops::{Add, Rem},
};
use allocative::Allocative;
use brk_error::Error;
use vecdb::{CheckedSub, FromCoarserIndex, Printable, StoredCompressed};
use jiff::Span;
use serde::Serialize;
use vecdb::{CheckedSub, FromCoarserIndex, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::{DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, WeekIndex, YearIndex};
@@ -28,6 +29,7 @@ use super::Date;
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct DateIndex(u16);
@@ -3,8 +3,9 @@ use std::{
ops::{Add, AddAssign, Div},
};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::{Date, DateIndex, YearIndex};
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, YearIndex};
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct DecadeIndex(u16);
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -25,6 +26,7 @@ use super::Height;
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct DifficultyEpoch(u16);
@@ -4,6 +4,7 @@ use std::{
ops::{Add, AddAssign, Div, Mul},
};
use allocative::Allocative;
use derive_deref::Deref;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, StoredCompressed};
@@ -24,6 +25,7 @@ use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64};
Serialize,
Deserialize,
StoredCompressed,
Allocative,
)]
pub struct Dollars(f64);
+11 -1
View File
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::Serialize;
use vecdb::StoredCompressed;
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -10,7 +11,16 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::{Sats, StoredU64};
#[derive(
Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout, StoredCompressed,
Debug,
Clone,
Copy,
Serialize,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct FeeRate(f64);
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -25,6 +26,7 @@ use super::Height;
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct HalvingEpoch(u16);
+2
View File
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Rem},
};
use allocative::Allocative;
use bitcoincore_rpc::{Client, RpcApi};
use byteview::ByteView;
use derive_deref::Deref;
@@ -32,6 +33,7 @@ use super::StoredU64;
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct Height(u32);
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign};
use allocative::Allocative;
use derive_deref::{Deref, DerefMut};
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
@@ -24,6 +25,7 @@ use super::Vin;
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct InputIndex(u64);
+3 -1
View File
@@ -3,8 +3,9 @@ use std::{
ops::{Add, AddAssign, Div},
};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::{Date, DateIndex, YearIndex};
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, YearIndex};
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct MonthIndex(u16);
+2
View File
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use derive_deref::{Deref, DerefMut};
use serde::{Serialize, Serializer, ser::SerializeTuple};
use vecdb::StoredCompressed;
@@ -473,6 +474,7 @@ where
DerefMut,
Serialize,
StoredCompressed,
Allocative,
)]
#[repr(transparent)]
pub struct Close<T>(T);
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign};
use allocative::Allocative;
use derive_deref::{Deref, DerefMut};
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
@@ -26,6 +27,7 @@ use super::Vout;
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct OutputIndex(u64);
@@ -16,6 +16,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
KnownLayout,
Serialize,
)]
#[serde(rename_all = "lowercase")]
#[repr(u8)]
pub enum OutputType {
P2PK65,
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -25,6 +26,7 @@ use super::MonthIndex;
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct QuarterIndex(u16);
+2
View File
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div, Mul, SubAssign},
};
use allocative::Allocative;
use bitcoin::Amount;
use derive_deref::Deref;
use serde::{Deserialize, Serialize};
@@ -30,6 +31,7 @@ use super::{Bitcoin, Cents, Dollars, Height};
Serialize,
Deserialize,
StoredCompressed,
Allocative,
)]
pub struct Sats(u64);
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -25,6 +26,7 @@ use super::MonthIndex;
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct SemesterIndex(u16);
@@ -1,3 +1,4 @@
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{Printable, StoredCompressed};
@@ -19,6 +20,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct StoredBool(u16);
@@ -6,11 +6,14 @@ use std::{
ops::{Add, AddAssign, Div, Mul, Sub},
};
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::{Close, StoredU32};
use super::{Dollars, StoredF64};
#[derive(
@@ -25,6 +28,7 @@ use super::{Dollars, StoredF64};
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct StoredF32(f32);
@@ -65,12 +69,24 @@ impl From<usize> for StoredF32 {
}
}
impl From<StoredU32> for StoredF32 {
fn from(value: StoredU32) -> Self {
Self(f32::from(value))
}
}
impl CheckedSub<StoredF32> for StoredF32 {
fn checked_sub(self, rhs: Self) -> Option<Self> {
Some(Self(self.0 - rhs.0))
}
}
impl CheckedSub<usize> for StoredF32 {
fn checked_sub(self, rhs: usize) -> Option<Self> {
Some(Self(self.0 - rhs as f32))
}
}
impl Div<usize> for StoredF32 {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
@@ -78,6 +94,13 @@ impl Div<usize> for StoredF32 {
}
}
impl Div<StoredU32> for StoredF32 {
type Output = Self;
fn div(self, rhs: StoredU32) -> Self::Output {
Self(self.0 / f32::from(rhs))
}
}
impl Add for StoredF32 {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
@@ -103,6 +126,12 @@ impl From<Dollars> for StoredF32 {
}
}
impl From<Close<Dollars>> for StoredF32 {
fn from(value: Close<Dollars>) -> Self {
Self::from(*value)
}
}
impl Div<Dollars> for StoredF32 {
type Output = Self;
fn div(self, rhs: Dollars) -> Self::Output {
@@ -4,6 +4,7 @@ use std::{
ops::{Add, AddAssign, Div, Mul},
};
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
@@ -23,6 +24,7 @@ use crate::{Bitcoin, Dollars};
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct StoredF64(f64);
@@ -1,3 +1,5 @@
use std::borrow::Cow;
use byteview::ByteView;
use derive_deref::Deref;
use serde::Serialize;
@@ -26,6 +28,12 @@ impl From<String> for StoredString {
}
}
impl From<Cow<'_, str>> for StoredString {
fn from(value: Cow<'_, str>) -> Self {
Self(value.to_string())
}
}
impl From<ByteView> for StoredString {
fn from(value: ByteView) -> Self {
let bytes = &*value;
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign, Div};
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
@@ -27,11 +28,13 @@ use super::{
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct StoredU16(u16);
impl StoredU16 {
pub const ZERO: Self = Self(0);
pub const ONE: Self = Self(1);
pub fn new(v: u16) -> Self {
Self(v)
+34 -1
View File
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign, Div};
use std::ops::{Add, AddAssign, Div, Mul};
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
@@ -27,15 +28,21 @@ use super::{
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct StoredU32(u32);
impl StoredU32 {
pub const ZERO: Self = Self(0);
pub const ONE: Self = Self(1);
pub fn new(counter: u32) -> Self {
Self(counter)
}
pub fn is_zero(&self) -> bool {
self.0 == 0
}
}
impl From<u32> for StoredU32 {
@@ -44,6 +51,12 @@ impl From<u32> for StoredU32 {
}
}
impl From<StoredU32> for f32 {
fn from(value: StoredU32) -> Self {
value.0 as f32
}
}
impl From<usize> for StoredU32 {
fn from(value: usize) -> Self {
if value > u32::MAX as usize {
@@ -59,6 +72,15 @@ impl CheckedSub<StoredU32> for StoredU32 {
}
}
impl CheckedSub<usize> for StoredU32 {
fn checked_sub(self, rhs: usize) -> Option<Self> {
if rhs > u32::MAX as usize {
panic!()
}
self.0.checked_sub(rhs as u32).map(Self)
}
}
impl Div<usize> for StoredU32 {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
@@ -79,6 +101,17 @@ impl AddAssign for StoredU32 {
}
}
impl Mul<usize> for StoredU32 {
type Output = Self;
fn mul(self, rhs: usize) -> Self::Output {
let res = self.0 as usize * rhs;
if res > u32::MAX as usize {
panic!()
}
Self::from(res)
}
}
impl From<f64> for StoredU32 {
fn from(value: f64) -> Self {
if value < 0.0 || value > u32::MAX as f64 {
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign, Div};
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::{CheckedSub, Printable, StoredCompressed};
@@ -28,6 +29,7 @@ use super::{
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct StoredU64(u64);
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign, Div};
use allocative::Allocative;
use derive_deref::Deref;
use jiff::{civil::date, tz::TimeZone};
use serde::Serialize;
@@ -23,6 +24,7 @@ use super::Date;
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct Timestamp(u32);
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign};
use allocative::Allocative;
use byteview::ByteView;
use derive_deref::{Deref, DerefMut};
use serde::Serialize;
@@ -27,6 +28,7 @@ use super::StoredU32;
KnownLayout,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct TxIndex(u32);
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -25,6 +26,7 @@ use super::{Date, DateIndex};
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct WeekIndex(u16);
+2
View File
@@ -1,5 +1,6 @@
use std::ops::{Add, AddAssign, Div};
use allocative::Allocative;
use derive_deref::Deref;
use serde::Serialize;
use vecdb::StoredCompressed;
@@ -20,6 +21,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
FromBytes,
Serialize,
StoredCompressed,
Allocative,
)]
pub struct Weight(u64);
@@ -3,6 +3,7 @@ use std::{
ops::{Add, AddAssign, Div},
};
use allocative::Allocative;
use serde::{Deserialize, Serialize};
use vecdb::{CheckedSub, Printable, StoredCompressed};
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, MonthIndex};
IntoBytes,
KnownLayout,
StoredCompressed,
Allocative,
)]
pub struct YearIndex(u16);
+4 -1
View File
@@ -572,6 +572,7 @@
&:has(input:checked) {
color: var(--color);
font-style: normal;
}
[data-screenshot="true"] &:has(input:not(:checked)) {
@@ -950,6 +951,7 @@
display: flex;
align-items: center;
gap: 1rem;
/*font-style: italic;*/
> legend,
> div {
@@ -1051,6 +1053,7 @@
&:has(input:not(:checked)) {
color: var(--off-color);
/*font-style: italic;*/
> span.main > span.name {
text-decoration-thickness: 1.5px;
@@ -1263,7 +1266,7 @@
}
td {
text-transform: lowercase;
text-transform: none;
}
a {
File diff suppressed because it is too large Load Diff
+447 -199
View File
@@ -124,9 +124,10 @@
* @param {Env} args.env
* @param {Colors} args.colors
* @param {VecIdToIndexes} args.vecIdToIndexes
* @param {Pools} args.pools
* @returns {PartialOptionsTree}
*/
function createPartialOptions({ env, colors, vecIdToIndexes }) {
function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
/**
* @template {string} S
* @typedef {Extract<VecId, `${S}${string}`>} StartsWith
@@ -213,6 +214,19 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
{ year: 2025, color: colors.pink, defaultActive: true },
]);
const cohortAll = /** @type {const} */ ({
key: "",
name: "",
title: "",
color: colors.orange,
});
const cohortAllForComparaison = /** @type {const} */ ({
key: "",
name: "all",
title: "",
color: colors.default,
});
const terms = /** @type {const} */ ([
{
key: "sth",
@@ -1722,14 +1736,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
createBaseSeries({
key: `${key}supply_half`,
name: "Halved",
color: colors.gray,
options: {
lineStyle: 4,
},
}),
createBaseSeries({
key: `${key}supply_in_profit`,
name: "In Profit",
@@ -1762,22 +1768,30 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_breakeven`,
name: useGroupName ? name : "Even",
name: useGroupName ? name : "breakeven",
color: colors.yellow,
}),
createBaseSeries({
key: `${key}supply_breakeven_in_btc`,
name: useGroupName ? name : "Even",
name: useGroupName ? name : "breakeven",
color: colors.yellow,
}),
createBaseSeries({
key: `${key}supply_breakeven_in_usd`,
name: useGroupName ? name : "Even",
name: useGroupName ? name : "breakeven",
color: colors.yellow,
}),
createBaseSeries({
key: `${key}supply_half`,
name: "half",
color: colors.gray,
options: {
lineStyle: 4,
},
}),
createBaseSeries({
key: `${key}supply_half_in_btc`,
name: useGroupName ? name : "Halved",
name: useGroupName ? name : "half",
color: "list" in args ? color : colors.gray,
options: {
lineStyle: 4,
@@ -1785,7 +1799,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_half_in_usd`,
name: useGroupName ? name : "Halved",
name: useGroupName ? name : "half",
color: "list" in args ? color : colors.gray,
options: {
lineStyle: 4,
@@ -1805,7 +1819,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_breakeven_rel_to_circulating_supply`,
name: "Even",
name: "breakeven",
color: colors.yellow,
}),
]
@@ -1822,7 +1836,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
createBaseSeries({
key: `${key}supply_breakeven_rel_to_own_supply`,
name: "Even",
name: "breakeven",
color: colors.yellow,
}),
createPriceLine({
@@ -1862,15 +1876,18 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
name,
color,
}),
...(key
? [
createBaseSeries({
key: `${key}supply_rel_to_circulating_supply`,
name,
color,
}),
]
: []),
key
? createBaseSeries({
key: `${key}supply_rel_to_circulating_supply`,
name,
color,
})
: createBaseSeries({
unit: "%all",
key: "constant_100",
name,
color,
}),
]);
}),
},
@@ -1904,11 +1921,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
createBaseSeries({
key: `${key}supply_in_profit_rel_to_own_supply`,
name,
color,
}),
]);
}),
},
@@ -1942,17 +1954,12 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
createBaseSeries({
key: `${key}supply_in_loss_rel_to_own_supply`,
name,
color,
}),
]);
}),
},
{
name: "even",
title: `Even Supply ${title}`,
name: "breakeven",
title: `Supply At Breaken ${title}`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
@@ -2006,11 +2013,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
},
...(list.filter(
({ key }) => `${fixKey(key)}addr_count` in vecIdToIndexes,
).length
).length > ("list" in args ? 1 : 0)
? !("list" in args) ||
list.filter(
({ key }) => `${fixKey(key)}empty_addr_count` in vecIdToIndexes,
).length == 0
).length <= 1
? [
{
name: "address count",
@@ -2103,7 +2110,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
{
name: "Price",
title: `Realized Price ${title}`,
top: args.list.map(({ color, name, key }) =>
top: list.map(({ color, name, key }) =>
createBaseSeries({
key: `${fixKey(key)}realized_price`,
name,
@@ -2111,6 +2118,23 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
),
},
{
name: "Ratio",
title: `Realized Price Ratio ${title}`,
bottom: [
...list.map(({ color, name, key }) =>
createBaseSeries({
key: `${fixKey(key)}realized_price_ratio`,
name,
color,
}),
),
createPriceLine({
unit: "Ratio",
number: 1,
}),
],
},
]
: createPriceWithRatioOptions({
title: `Realized Price ${title}`,
@@ -2144,23 +2168,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
...(`${key}realized_cap_rel_to_own_market_cap` in
vecIdToIndexes
? [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${key}realized_cap_rel_to_own_market_cap`,
title: "ratio",
options: { baseValue: { price: 100 } },
colors: [colors.red, colors.green],
}),
createPriceLine({
unit: "%cmcap",
defaultActive: true,
number: 100,
}),
]
: []),
]);
}),
},
@@ -2175,29 +2182,35 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
name: "Profit",
color: colors.green,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_profit_cumulative`,
name: "Cumulative Profit",
color: colors.green,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_loss`,
name: "Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}total_realized_pnl`,
name: "Total",
color: colors.default,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_realized_loss`,
name: "Negative Loss",
color: colors.red,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_profit_cumulative`,
name: "Cumulative Profit",
color: colors.green,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized_loss_cumulative`,
name: "Cumulative Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_realized_loss`,
name: "Negative Loss",
color: colors.red,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_realized_loss_cumulative`,
name: "Cumulative Negative Loss",
@@ -2433,6 +2446,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
],
},
{
name: "Total pnl",
title: `Total Realized Profit And Loss Loss ${title}`,
bottom: [
...list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `${key}total_realized_pnl`,
name,
color,
}),
]);
}),
],
},
{
name: "Net pnl",
title: `Net Realized Profit And Loss ${title}`,
@@ -2613,7 +2642,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
]),
{
name: "Sell Side Risk Ratio",
name: "Sell Side Risk",
title: `Sell Side Risk Ratio ${title}`,
bottom: !("list" in args)
? list.flatMap(({ key }) => [
@@ -2655,8 +2684,8 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
title: `Unrealized Profit And Loss ${title}`,
bottom: [
createBaseSeries({
key: `${fixKey(args.key)}unrealized_total_pnl`,
name: "profit+loss",
key: `${fixKey(args.key)}total_unrealized_pnl`,
name: "total",
color: colors.default,
}),
createBaseSeries({
@@ -2719,22 +2748,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
...(`${fixKey(args.key)}unrealized_profit_rel_to_own_unrealized_total_pnl` in
...(`${fixKey(args.key)}unrealized_profit_rel_to_own_total_unrealized_pnl` in
vecIdToIndexes
? [
createBaseSeries({
key: `${fixKey(args.key)}unrealized_profit_rel_to_own_unrealized_total_pnl`,
key: `${fixKey(args.key)}unrealized_profit_rel_to_own_total_unrealized_pnl`,
name: "Profit",
color: colors.green,
}),
createBaseSeries({
key: `${fixKey(args.key)}unrealized_loss_rel_to_own_unrealized_total_pnl`,
key: `${fixKey(args.key)}unrealized_loss_rel_to_own_total_unrealized_pnl`,
name: "Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}neg_unrealized_loss_rel_to_own_unrealized_total_pnl`,
key: `${fixKey(args.key)}neg_unrealized_loss_rel_to_own_total_unrealized_pnl`,
name: "Negative Loss",
color: colors.red,
}),
@@ -2767,8 +2796,8 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
return /** @type {const} */ ([
createBaseSeries({
key: `${key}unrealized_profit`,
name: useGroupName ? name : "Profit",
color: useGroupName ? color : colors.green,
name,
color,
}),
]);
}),
@@ -2781,8 +2810,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
return /** @type {const} */ ([
createBaseSeries({
key: `${key}unrealized_loss`,
name: useGroupName ? name : "Loss",
color: useGroupName ? color : colors.red,
name,
color,
}),
]);
}),
},
{
name: "total pnl",
title: `Unrealized Total Profit And Loss ${title}`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `${key}total_unrealized_pnl`,
name,
color,
}),
]);
}),
@@ -2821,14 +2864,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
]
: []),
...(`${fixKey(key)}net_unrealized_pnl_rel_to_own_unrealized_total_pnl` in
...(`${fixKey(key)}net_unrealized_pnl_rel_to_own_total_unrealized_pnl` in
vecIdToIndexes
? [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
)}net_unrealized_pnl_rel_to_own_unrealized_total_pnl`,
)}net_unrealized_pnl_rel_to_own_total_unrealized_pnl`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
}),
@@ -3293,10 +3336,31 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
...createSumCumulativeSeries({
concat: "block_count",
}),
createPriceLine({
unit: "Count",
createBaseSeries({
key: "block_count_target",
name: "Target",
number: 144,
color: colors.gray,
options: {
lineStyle: 4,
},
}),
createBaseSeries({
key: "1w_block_count",
name: "1w sum",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: "1m_block_count",
name: "1m sum",
color: colors.pink,
defaultActive: false,
}),
createBaseSeries({
key: "1y_block_count",
name: "1y sum",
color: colors.purple,
defaultActive: false,
}),
],
},
@@ -3476,87 +3540,116 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
],
},
{
name: "Coinbase",
title: "Coinbase",
bottom: [
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
key: "coinbase",
name: "Rewards",
tree: [
{
name: "Coinbase",
}),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
key: "coinbase_in_btc",
name: "Coinbase",
}),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
key: "coinbase_in_usd",
name: "Coinbase",
}),
],
},
{
name: "Subsidy",
title: "Subsidy",
bottom: [
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
key: "subsidy",
title: "Coinbase",
bottom: [
...createBaseAverageSumCumulativeMinMaxPercentilesSeries(
{
key: "coinbase",
name: "Coinbase",
},
),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries(
{
key: "coinbase_in_btc",
name: "Coinbase",
},
),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries(
{
key: "coinbase_in_usd",
name: "Coinbase",
},
),
],
},
{
name: "Subsidy",
}),
createBaseSeries({
key: "subsidy_usd_1y_sma",
name: "1y sma",
}),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
key: "subsidy_in_btc",
name: "Subsidy",
}),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
key: "subsidy_in_usd",
name: "Subsidy",
}),
],
},
{
name: "Fee",
title: "Transaction Fee",
bottom: [
...createAverageSumCumulativeMinMaxPercentilesSeries("fee"),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee_in_btc",
),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee_in_usd",
),
],
},
{
name: "Dominance",
title: "Reward Dominance",
bottom: [
createBaseSeries({
key: "fee_dominance",
title: "Subsidy",
bottom: [
...createBaseAverageSumCumulativeMinMaxPercentilesSeries(
{
key: "subsidy",
name: "Subsidy",
},
),
createBaseSeries({
key: "subsidy_usd_1y_sma",
name: "1y sma",
}),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries(
{
key: "subsidy_in_btc",
name: "Subsidy",
},
),
...createBaseAverageSumCumulativeMinMaxPercentilesSeries(
{
key: "subsidy_in_usd",
name: "Subsidy",
},
),
],
},
{
name: "Fee",
color: colors.amber,
}),
createBaseSeries({
key: "subsidy_dominance",
name: "Subsidy",
color: colors.red,
}),
],
},
{
name: "Unclaimed Rewards",
title: "Unclaimed Rewards",
bottom: [
...createSumCumulativeSeries({
concat: "unclaimed_rewards",
}),
...createSumCumulativeSeries({
concat: "unclaimed_rewards_in_btc",
}),
...createSumCumulativeSeries({
concat: "unclaimed_rewards_in_usd",
}),
title: "Transaction Fee",
bottom: [
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee",
),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee_in_btc",
),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee_in_usd",
),
],
},
{
name: "Dominance",
title: "Reward Dominance",
bottom: [
createBaseSeries({
key: "fee_dominance",
name: "Fee",
color: colors.amber,
}),
createBaseSeries({
key: "subsidy_dominance",
name: "Subsidy",
color: colors.red,
}),
],
},
{
name: "Unclaimed",
title: "Unclaimed Rewards",
bottom: [
...createSumCumulativeSeries({
concat: "unclaimed_rewards",
}),
...createSumCumulativeSeries({
concat: "unclaimed_rewards_in_btc",
}),
...createSumCumulativeSeries({
concat: "unclaimed_rewards_in_usd",
}),
],
},
{
name: "Puell multiple",
title: "Puell multiple",
bottom: [
createBaseSeries({
key: "puell_multiple",
name: "Multiple",
}),
],
},
],
},
{
@@ -3569,16 +3662,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
],
},
{
name: "Puell multiple",
title: "Puell multiple",
bottom: [
createBaseSeries({
key: "puell_multiple",
name: "Multiple",
}),
],
},
{
name: "Difficulty",
title: "Difficulty",
@@ -3650,6 +3733,165 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
}),
],
},
{
name: "Pools",
tree: Object.entries(pools).map(([_key, name]) => {
const key = /** @type {Pool} */ (_key);
return {
name,
tree: [
// indexes_to_dominance: ComputedVecsFromDateIndex<StoredF32>,
// indexes_to_1d_dominance: ComputedVecsFromDateIndex<StoredF32>,
// indexes_to_1w_dominance: ComputedVecsFromDateIndex<StoredF32>,
// indexes_to_1m_dominance: ComputedVecsFromDateIndex<StoredF32>,
// indexes_to_1y_dominance: ComputedVecsFromDateIndex<StoredF32>,
// indexes_to_days_since_block: ComputedVecsFromDateIndex<StoredU16>,
{
name: "Dominance",
title: `Dominance of ${name}`,
bottom: [
createBaseSeries({
key: `${key}_1d_dominance`,
name: "1d",
color: colors.rose,
defaultActive: false,
}),
createBaseSeries({
key: `${key}_1w_dominance`,
name: "1w",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${key}_1m_dominance`,
name: "1m",
}),
createBaseSeries({
key: `${key}_1y_dominance`,
name: "1y",
color: colors.lime,
defaultActive: false,
}),
createBaseSeries({
key: `${key}_dominance`,
name: "all time",
color: colors.teal,
defaultActive: false,
}),
],
},
{
name: "Blocks mined",
title: `Blocks mined by ${name}`,
bottom: [
createBaseSeries({
key: `${key}_blocks_mined`,
name: "Sum",
}),
createBaseSeries({
key: `${key}_blocks_mined_cumulative`,
name: "Cumulative",
color: colors.blue,
}),
createBaseSeries({
key: `${key}_1w_blocks_mined`,
name: "1w Sum",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${key}_1m_blocks_mined`,
name: "1m Sum",
color: colors.pink,
defaultActive: false,
}),
createBaseSeries({
key: `${key}_1y_blocks_mined`,
name: "1y Sum",
color: colors.purple,
defaultActive: false,
}),
],
},
{
name: "Rewards",
tree: [
{
name: "coinbase",
title: `coinbase collected by ${name}`,
bottom: [
...createSumCumulativeSeries({
concat: `${key}_coinbase`,
common: "coinbase",
// cumulativeColor: colors.
}),
...createSumCumulativeSeries({
concat: `${key}_coinbase_in_btc`,
common: "coinbase",
// cumulativeColor: colors.
}),
...createSumCumulativeSeries({
concat: `${key}_coinbase_in_usd`,
common: "coinbase",
}),
],
},
{
name: "subsidy",
title: `subsidy collected by ${name}`,
bottom: [
...createSumCumulativeSeries({
concat: `${key}_subsidy`,
common: "subsidy",
// cumulativeColor: colors.
}),
...createSumCumulativeSeries({
concat: `${key}_subsidy_in_btc`,
common: "subsidy",
// cumulativeColor: colors.
}),
...createSumCumulativeSeries({
concat: `${key}_subsidy_in_usd`,
common: "subsidy",
}),
],
},
{
name: "fees",
title: `fees collected by ${name}`,
bottom: [
...createSumCumulativeSeries({
concat: `${key}_fee`,
common: "fee",
// cumulativeColor: colors.
}),
...createSumCumulativeSeries({
concat: `${key}_fee_in_btc`,
common: "fee",
// cumulativeColor: colors.
}),
...createSumCumulativeSeries({
concat: `${key}_fee_in_usd`,
common: "fee",
}),
],
},
],
},
{
name: "Days since block",
title: `Days since ${name} mined a block`,
bottom: [
createBaseSeries({
key: `${key}_days_since_block`,
name: "Raw",
}),
],
},
],
};
}),
},
],
},
{
@@ -3722,19 +3964,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
{
name: "Cohorts",
tree: [
createCohortGroupFolder({
key: "",
name: "",
title: "",
color: colors.orange,
}),
createCohortGroupFolder(cohortAll),
{
name: "terms",
tree: [
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Term",
list: terms,
list: [...terms, cohortAllForComparaison],
}),
...terms.map(createCohortGroupFolder),
],
@@ -3745,7 +3982,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Epoch",
list: epoch,
list: [...epoch, cohortAllForComparaison],
}),
...epoch.map(createCohortGroupFolder),
],
@@ -3756,7 +3993,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Type",
list: type,
list: [...type, cohortAllForComparaison],
}),
...type.map(createCohortGroupFolder),
],
@@ -3767,7 +4004,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Up To Age",
list: upToDate,
list: [...upToDate, cohortAllForComparaison],
}),
...upToDate.map(createCohortGroupFolder),
],
@@ -3778,7 +4015,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs from age",
list: fromDate,
list: [...fromDate, cohortAllForComparaison],
}),
...fromDate.map(createCohortGroupFolder),
],
@@ -3789,7 +4026,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Age Range",
list: dateRange,
list: [...dateRange, cohortAllForComparaison],
}),
...dateRange.map(createCohortGroupFolder),
],
@@ -3800,7 +4037,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs under amount",
list: utxosUnderAmount,
list: [...utxosUnderAmount, cohortAllForComparaison],
}),
...utxosUnderAmount.map(createCohortGroupFolder),
],
@@ -3811,7 +4048,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs Above Amount",
list: utxosAboveAmount,
list: [...utxosAboveAmount, cohortAllForComparaison],
}),
...utxosAboveAmount.map(createCohortGroupFolder),
],
@@ -3822,7 +4059,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "UTXOs between amounts",
list: utxosAmountRanges,
list: [...utxosAmountRanges, cohortAllForComparaison],
}),
...utxosAmountRanges.map(createCohortGroupFolder),
],
@@ -3833,7 +4070,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Addresses under Amount",
list: addressesUnderAmount,
list: [...addressesUnderAmount, cohortAllForComparaison],
}),
...addressesUnderAmount.map(createCohortGroupFolder),
],
@@ -3844,7 +4081,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Addresses above amount",
list: addressesAboveAmount,
list: [...addressesAboveAmount, cohortAllForComparaison],
}),
...addressesAboveAmount.map(createCohortGroupFolder),
],
@@ -3855,7 +4092,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
createCohortGroupFolder({
name: "Compare",
title: "Addresses between amounts",
list: addressesAmountRanges,
list: [...addressesAmountRanges, cohortAllForComparaison],
}),
...addressesAmountRanges.map(createCohortGroupFolder),
],
@@ -4144,6 +4381,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
* @param {Env} args.env
* @param {Utilities} args.utils
* @param {VecIdToIndexes} args.vecIdToIndexes
* @param {Pools} args.pools
* @param {Signal<string | null>} args.qrcode
*/
export function initOptions({
@@ -4153,22 +4391,28 @@ export function initOptions({
utils,
qrcode,
vecIdToIndexes,
pools,
}) {
const LS_SELECTED_KEY = `selected_id`;
const LS_SELECTED_KEY = `selected_path`;
const urlPath_ = window.document.location.pathname
.split("/")
.filter((v) => v);
const urlPath = urlPath_.length ? urlPath_ : undefined;
const savedPath = utils.storage
.read(LS_SELECTED_KEY)
?.split("/")
.filter((v) => v);
const savedPath = /** @type {string[]} */ (
JSON.parse(utils.storage.read(LS_SELECTED_KEY) || "[]") || []
).filter((v) => v);
console.log(savedPath);
/** @type {Signal<Option>} */
const selected = signals.createSignal(/** @type {any} */ (undefined));
const partialOptions = createPartialOptions({ env, colors, vecIdToIndexes });
const partialOptions = createPartialOptions({
env,
colors,
vecIdToIndexes,
pools,
});
/** @type {Option[]} */
const list = [];
@@ -4196,6 +4440,7 @@ export function initOptions({
function selectOption(option) {
utils.url.pushHistory(option.path);
utils.url.resetParams(option);
utils.storage.write(LS_SELECTED_KEY, JSON.stringify(option.path));
selected.set(option);
}
@@ -4308,11 +4553,11 @@ export function initOptions({
);
const serName = utils.stringToId(anyPartial.name);
const path = [...parentPath, serName];
const childOptionsCount = recursiveProcessPartialTree(
anyPartial.tree,
passedDetails,
[...parentPath, serName],
path,
depth + 1,
);
@@ -4325,7 +4570,10 @@ export function initOptions({
}
signals.createEffect(selected, (selected) => {
if (selected.path[depth] === serName) {
if (
path.length <= selected.path.length &&
path.every((v, i) => selected.path.at(i) === v)
) {
li.dataset.highlight = "";
} else {
delete li.dataset.highlight;
+6 -3
View File
@@ -515,12 +515,15 @@ function createIndexToVecIds(vecIdToIndexes) {
/**
* @param {Object} args
* @param {number | OHLCTuple} args.value
* @param {number | string | Object | Array<any>} args.value
* @param {Unit} args.unit
*/
function serializeValue({ value, unit }) {
if (typeof value !== "number") {
return JSON.stringify(value);
const t = typeof value;
if (typeof value === "string") {
return value;
} else if (t !== "number") {
return JSON.stringify(value).replaceAll('"', "").slice(1, -1);
} else if (value !== 18446744073709552000) {
if (unit === "USD" || unit === "Difficulty" || unit === "sat/vB") {
return value.toLocaleString("en-us", {