mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-26 14:14:30 -07:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8ee4cf57f | |||
| b39548b4c6 | |||
| 4217c22ff6 | |||
| 4ab10670c9 | |||
| 2883f88de6 | |||
| e002a61a19 | |||
| 5893376279 | |||
| 411c5e4c4d | |||
| c2a77072d2 | |||
| c8a25934a6 | |||
| 7b38355cd4 | |||
| ddc54e0b98 | |||
| 8a7003782b | |||
| 8e6464dacb | |||
| 92b1dc0afb | |||
| 7562f51e07 | |||
| 09bba99e68 | |||
| 9d674cd49b | |||
| 88a0c9ea03 | |||
| 5014e0ce3e | |||
| b7a1ee9ebc | |||
| 292ceddd66 | |||
| 4b52b80000 | |||
| 9f20664c6e | |||
| 851a6aac0e | |||
| 1f1e73c47a |
Generated
+174
-192
@@ -30,15 +30,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom 0.2.16",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy 0.7.35",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -127,12 +127,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.7"
|
||||
version = "3.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||
checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@@ -288,9 +288,9 @@ checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d"
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin"
|
||||
version = "0.32.5"
|
||||
version = "0.32.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026"
|
||||
checksum = "ad8929a18b8e33ea6b3c09297b687baaa71fb1b97353243a3f1029fad5c59c5b"
|
||||
dependencies = [
|
||||
"base58ck",
|
||||
"bech32",
|
||||
@@ -366,9 +366,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.0"
|
||||
version = "2.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@@ -381,7 +381,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"brk_cli",
|
||||
"brk_computer",
|
||||
@@ -398,7 +398,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_cli"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"brk_computer",
|
||||
"brk_core",
|
||||
@@ -421,7 +421,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_computer"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"brk_exit",
|
||||
@@ -433,19 +433,23 @@ dependencies = [
|
||||
"clap",
|
||||
"clap_derive",
|
||||
"color-eyre",
|
||||
"derive_deref",
|
||||
"fjall",
|
||||
"log",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"zerocopy",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_core"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
"byteview",
|
||||
"byteview 0.7.0",
|
||||
"derive_deref",
|
||||
"jiff",
|
||||
"log",
|
||||
@@ -454,13 +458,13 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"serde_derive",
|
||||
"zerocopy 0.8.25",
|
||||
"zerocopy-derive 0.8.25",
|
||||
"zerocopy",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_exit"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"brk_logger",
|
||||
"ctrlc",
|
||||
@@ -469,7 +473,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_fetcher"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"brk_logger",
|
||||
@@ -482,7 +486,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_indexer"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -491,17 +495,17 @@ dependencies = [
|
||||
"brk_logger",
|
||||
"brk_parser",
|
||||
"brk_vec",
|
||||
"byteview",
|
||||
"byteview 0.7.0",
|
||||
"color-eyre",
|
||||
"fjall",
|
||||
"log",
|
||||
"rayon",
|
||||
"zerocopy 0.8.25",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_logger"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"env_logger",
|
||||
@@ -511,7 +515,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_parser"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -521,12 +525,12 @@ dependencies = [
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"zerocopy 0.8.25",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brk_query"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"brk_computer",
|
||||
"brk_indexer",
|
||||
@@ -543,7 +547,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_server"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"brk_computer",
|
||||
@@ -571,7 +575,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_vec"
|
||||
version = "0.0.32"
|
||||
version = "0.0.40"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"brk_core",
|
||||
@@ -583,8 +587,8 @@ dependencies = [
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"zerocopy 0.8.25",
|
||||
"zerocopy-derive 0.8.25",
|
||||
"zerocopy",
|
||||
"zerocopy-derive",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
@@ -642,6 +646,12 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6236364b88b9b6d0bc181ba374cf1ab55ba3ef97a1cb6f8cddad48a273767fb5"
|
||||
|
||||
[[package]]
|
||||
name = "byteview"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f996a0c883b1ae93c53ffd21857b6eaba768998dbb1f7e2f269d53dd6553256c"
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.5.2"
|
||||
@@ -672,9 +682,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.21"
|
||||
version = "1.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0"
|
||||
checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -718,18 +728,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.37"
|
||||
version = "4.5.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||
checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.37"
|
||||
version = "4.5.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||
checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -835,21 +845,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
|
||||
dependencies = [
|
||||
"crc-catalog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc-catalog"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
@@ -937,9 +932,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.6"
|
||||
version = "3.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c"
|
||||
checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"windows-sys 0.59.0",
|
||||
@@ -1098,9 +1093,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.11"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
|
||||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
@@ -1135,7 +1130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b929b3db7be7d7b4d4df67fb016fc446b8f57507b48a82e69d2a30610e460f28"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"byteview",
|
||||
"byteview 0.6.1",
|
||||
"dashmap",
|
||||
"log",
|
||||
"lsm-tree",
|
||||
@@ -1152,6 +1147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"libz-rs-sys",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
@@ -1238,9 +1234,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
@@ -1388,9 +1384,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.11"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
|
||||
checksum = "cf9f1e950e0d9d1d3c47184416723cf29c0d1f93bd8cccf37e4beb6b44f31710"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-util",
|
||||
@@ -1501,9 +1497,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "jiff"
|
||||
version = "0.2.13"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806"
|
||||
checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
|
||||
dependencies = [
|
||||
"jiff-static",
|
||||
"jiff-tzdb-platform",
|
||||
@@ -1516,9 +1512,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jiff-static"
|
||||
version = "0.2.13"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48"
|
||||
checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1546,7 +1542,7 @@ version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.2",
|
||||
"getrandom 0.3.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -1584,6 +1580,35 @@ version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "liblzma"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66352d7a8ac12d4877b6e6ea5a9b7650ee094257dc40889955bea5bc5b08c1d0"
|
||||
dependencies = [
|
||||
"liblzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "liblzma-sys"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5839bad90c3cc2e0b8c4ed8296b80e86040240f81d46b9c0e9bc8dd51ddd3af1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-rs-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a"
|
||||
dependencies = [
|
||||
"zlib-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
@@ -1636,27 +1661,6 @@ version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
|
||||
|
||||
[[package]]
|
||||
name = "lzma-rs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-sys"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.8.4"
|
||||
@@ -1720,9 +1724,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@@ -1785,6 +1789,12 @@ version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "outref"
|
||||
version = "0.5.2"
|
||||
@@ -1793,15 +1803,15 @@ checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.2.0"
|
||||
version = "4.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
|
||||
checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec"
|
||||
|
||||
[[package]]
|
||||
name = "oxc"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f907527226ea09664a17963b36d3057ddcab280c1dcc19b3a287f40de30c3965"
|
||||
checksum = "86a761cfb7ce8c7d07e0bb5a43d8676ae69de62b2d19a542c131784049ad22cb"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -1842,23 +1852,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_allocator"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3da7bc2d06c0fd029c7817889b1e4d418f4955c25c003d5a9ea4a525db8fce9"
|
||||
checksum = "0769ed37977fc61b76ee89fe955b184db62b07e62609388ad6e6a1eb046837e3"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"bumpalo",
|
||||
"hashbrown 0.15.3",
|
||||
"oxc_data_structures",
|
||||
"rustc-hash",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ast"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a83d102ba84b604cf24be6b943c3347f13740afa97304461d798f2598d4a92e"
|
||||
checksum = "17c6c770d1e86a9c4710d9c7974bf79e573b48efa3a764698477c11035c65738"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -1873,10 +1882,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ast_macros"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e03da9a237d05fa378e3398a5a2c28124a387ff666218c1ca4ebfe5f0544d3d"
|
||||
checksum = "9c08ec3f117c0370106cf39b274090ae7f0b2be48b6bcae794bdc92fd1d34f22"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
@@ -1884,9 +1894,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ast_visit"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f97a1716d68a3c9a0c9cf1d906eaeaa3a806052f91d8e4ef14e6afc50d515132"
|
||||
checksum = "3b6fc584d5c7e5bd8394208a01d2d33025afcc8abceaed85455d642ee11db998"
|
||||
dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -1896,9 +1906,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_cfg"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de348366d30393be8eab6591bfa03c63c18e0b239cccf666554769547d94cd39"
|
||||
checksum = "35a48bb41100a00b9a647c9aacd7fe6412d03a1c623a8285a9e514c2fa49e447"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"itertools",
|
||||
@@ -1911,9 +1921,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_codegen"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "740de9affaf00644d8122c3e74009c01888747d7233487c387415b298c5f9fd4"
|
||||
checksum = "cf726a55fd107703b21b728c044a2e64c71242d35514c4e7e1c4c7dffca98220"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -1932,15 +1942,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_data_structures"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9603941570dc1dbc111e6312d622d60722395b502aa68e703646beacc45d0d2"
|
||||
checksum = "374638f55291a87994e37c715c9a312be3e29dfac5dd5a655847a3d4f98d2b63"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_diagnostics"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a01184ff8ddf40a39c5ec4b0979b53e6e3f8e5701e4a0aed8edefd208ae310eb"
|
||||
checksum = "c4f29efa3f609ea53f193b1ffc19f548a6ac5464f27ad20a27982d623fc5784a"
|
||||
dependencies = [
|
||||
"cow-utils",
|
||||
"oxc-miette",
|
||||
@@ -1948,9 +1961,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_ecmascript"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d549b884069d155eae98207c404b71113dc8fce2bea84dc53e8476a221405a83"
|
||||
checksum = "b0f469ed7c14f5a2d75f39af03517d3d0da071ae2c33c91cd75f547f434b978d"
|
||||
dependencies = [
|
||||
"cow-utils",
|
||||
"num-bigint",
|
||||
@@ -1962,9 +1975,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_estree"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66904246cb3ceef3c7f9dd4b3a79bb104b242d8e442eb94f6097cec241a0eec4"
|
||||
checksum = "5bf9a77d3465740411872becbf9fc43d0462ba3adb6f2609334c1b75365dfde3"
|
||||
|
||||
[[package]]
|
||||
name = "oxc_index"
|
||||
@@ -1974,9 +1987,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392"
|
||||
|
||||
[[package]]
|
||||
name = "oxc_mangler"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d862ba81d295897e817489c0850b04c41facb927bf760d808778da40cc7ad580"
|
||||
checksum = "68675862106f3ad0177dce45db81d27f406d0f27ac27541b55a60953ed5358e8"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"itertools",
|
||||
@@ -1991,9 +2004,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_minifier"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465c3ce7241550963b95a7127879e83a5f64094bdf217eb393e209b9eb9bed9c"
|
||||
checksum = "aa89cd8c32768a12f50d949d2ad602262f3104ceca5504947850ee6c39aeaadc"
|
||||
dependencies = [
|
||||
"cow-utils",
|
||||
"oxc_allocator",
|
||||
@@ -2013,9 +2026,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_parser"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a662d53b21550ca1a5600f70d033fcec40b2a25ba2b5281ecaf2ecd01cb16559"
|
||||
checksum = "848bc15e9fd22229224593e1468ae4d2cf8d396157b5ba9938daecbbac9a1409"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -2036,14 +2049,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_regular_expression"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c53f760363c78764bb28b8e0f8316d9c28adf89a0ddfba625c8a9f465f4e2199"
|
||||
checksum = "6ef0bc791b7a19124561c8c285cbb0f25e7cd5e4201b9bfd770b96b5f3bcdf79"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"oxc_allocator",
|
||||
"oxc_ast_macros",
|
||||
"oxc_diagnostics",
|
||||
"oxc_estree",
|
||||
"oxc_span",
|
||||
"phf",
|
||||
"rustc-hash",
|
||||
@@ -2052,9 +2065,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_semantic"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942de11616459d462489166eddf7870cfb8589ba3f12b91f61d28e80b77f7fd0"
|
||||
checksum = "e796ba52fa9b3c8dbc8fd3e57f5085f80dde092244098049dfa5732180304ed6"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"oxc_allocator",
|
||||
@@ -2074,9 +2087,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_sourcemap"
|
||||
version = "3.0.0"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6665c417b2aa1c426a7b142bcc0d2f47d9fee9e6f88610f054cfa7ce6623001e"
|
||||
checksum = "24015d93ed1d8f0c2a0d9f534ca85690888990658a8fc4a87ff0c92640e73300"
|
||||
dependencies = [
|
||||
"base64-simd",
|
||||
"cfg-if",
|
||||
@@ -2088,9 +2101,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_span"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f8e3cd484054ea0ce496e16437d802d4d9126e238deb267796db140a80d91dc"
|
||||
checksum = "b2c1bcdd7b1695ac01ddcde35bc7b69b72150857d14e696f82f8a38927e7ceb3"
|
||||
dependencies = [
|
||||
"compact_str",
|
||||
"oxc-miette",
|
||||
@@ -2101,9 +2114,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_syntax"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8933bda357ccc13260bb2fe3a08f02d98ceeb695c9af04d8ec5913edd9bec6d6"
|
||||
checksum = "934fcc154f95afb172f84d250fe42833745eb06e83ced8a4e5d6669b9348528f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cow-utils",
|
||||
@@ -2122,9 +2135,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_traverse"
|
||||
version = "0.68.1"
|
||||
version = "0.72.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e318be8193f3c72ab703afbb8941b31ed475168514067337325fa151416301a"
|
||||
checksum = "4e394bf07dc65a0f15eee42a5410a6e975def23c498cc7ecd38e19c286866aea"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"oxc_allocator",
|
||||
@@ -2305,7 +2318,7 @@ version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy 0.8.25",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2341,9 +2354,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quick_cache"
|
||||
version = "0.6.13"
|
||||
version = "0.6.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "287e56aac5a2b4fb25a6fb050961d157635924c8696305a5c937a76f29841a0f"
|
||||
checksum = "6b450dad8382b1b95061d5ca1eb792081fb082adf48c678791fe917509596d5f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.3",
|
||||
@@ -2530,9 +2543,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@@ -2738,12 +2751,6 @@ version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
@@ -2850,12 +2857,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.19.1"
|
||||
version = "3.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
|
||||
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.3.2",
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
@@ -3043,9 +3050,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1cfca9ae570b2a6efc764a88e914c29b3dfaa1fafe5f495812ae97ec9bc4d53"
|
||||
checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"bitflags",
|
||||
@@ -3182,7 +3189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62fc7c4ce161f049607ecea654dca3f2d727da5371ae85e2e4f14ce2b98ed67c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"byteview",
|
||||
"byteview 0.6.1",
|
||||
"interval-heap",
|
||||
"log",
|
||||
"path-absolutize",
|
||||
@@ -3291,9 +3298,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.0"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
@@ -3332,18 +3339,18 @@ checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.2"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.0"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
@@ -3454,42 +3461,13 @@ version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
|
||||
|
||||
[[package]]
|
||||
name = "xz2"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
|
||||
dependencies = [
|
||||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.8.25",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3525,32 +3503,36 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "2.6.1"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744"
|
||||
checksum = "153a6fff49d264c4babdcfa6b4d534747f520e56e8f0f384f3b808c4b64cc1fd"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arbitrary",
|
||||
"bzip2",
|
||||
"constant_time_eq",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"deflate64",
|
||||
"flate2",
|
||||
"getrandom 0.3.2",
|
||||
"getrandom 0.3.3",
|
||||
"hmac",
|
||||
"indexmap 2.9.0",
|
||||
"lzma-rs",
|
||||
"liblzma",
|
||||
"memchr",
|
||||
"pbkdf2",
|
||||
"sha1",
|
||||
"time",
|
||||
"xz2",
|
||||
"zeroize",
|
||||
"zopfli",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
version = "0.8.2"
|
||||
|
||||
+5
-5
@@ -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.32"
|
||||
package.version = "0.0.40"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
|
||||
[profile.release]
|
||||
@@ -17,7 +17,7 @@ inherits = "release"
|
||||
|
||||
[workspace.dependencies]
|
||||
axum = "0.8.4"
|
||||
bitcoin = { version = "0.32.5", features = ["serde"] }
|
||||
bitcoin = { version = "0.32.6", features = ["serde"] }
|
||||
bitcoincore-rpc = "0.19.0"
|
||||
brk_cli = { version = "0", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0", path = "crates/brk_computer" }
|
||||
@@ -30,13 +30,13 @@ brk_parser = { version = "0", path = "crates/brk_parser" }
|
||||
brk_query = { version = "0", path = "crates/brk_query" }
|
||||
brk_server = { version = "0", path = "crates/brk_server" }
|
||||
brk_vec = { version = "0", path = "crates/brk_vec" }
|
||||
byteview = "0.6.1"
|
||||
clap = { version = "4.5.37", features = ["string"] }
|
||||
byteview = "0.7.0"
|
||||
clap = { version = "4.5.38", features = ["string"] }
|
||||
clap_derive = "4.5.32"
|
||||
color-eyre = "0.6.4"
|
||||
derive_deref = "1.1.1"
|
||||
fjall = "2.10.0"
|
||||
jiff = "0.2.13"
|
||||
jiff = "0.2.14"
|
||||
log = { version = "0.4.27" }
|
||||
minreq = { version = "2.13.4", features = ["https", "serde_json"] }
|
||||
rayon = "1.10.0"
|
||||
|
||||
@@ -93,8 +93,10 @@ If you'd like to have your own instance hosted for you please contact [hosting@b
|
||||
|
||||
- 2 separate dedicated servers (1 GB/s each) with different ISPs and Cloudflare integration for enhanced performance and optimal availability
|
||||
- 99.9% SLA
|
||||
- Direct communication for feature requests and support
|
||||
- Configurated for speed (`raw + eager`)
|
||||
- Updates delivered at your convenience
|
||||
- Direct communication for feature requests and support
|
||||
- Bitcoin Core or Knots with desired version
|
||||
- Optional subdomains: `*.bitcoinresearchkit.org`, `*.kibo.money` and `*.satonomics.xyz`
|
||||
- Logo featured in the Readme if desired
|
||||
|
||||
|
||||
+67
-59
@@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
thread::sleep,
|
||||
thread::{self, sleep},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
@@ -33,77 +33,85 @@ pub fn run(config: RunConfig) -> color_eyre::Result<()> {
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let mut computer = Computer::new(&config.outputsdir(), config.fetcher(), compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs(&indexer, config.computation())?;
|
||||
let wait_for_synced_node = || -> color_eyre::Result<()> {
|
||||
let is_synced = || -> color_eyre::Result<bool> {
|
||||
let info = rpc.get_blockchain_info()?;
|
||||
Ok(info.headers == info.blocks)
|
||||
};
|
||||
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()?
|
||||
.block_on(async {
|
||||
let server = if config.serve() {
|
||||
let served_indexer = indexer.clone();
|
||||
let served_computer = computer.clone();
|
||||
if !is_synced()? {
|
||||
info!("Waiting for node to be synced...");
|
||||
while !is_synced()? {
|
||||
sleep(Duration::from_secs(1))
|
||||
}
|
||||
}
|
||||
|
||||
let server = Server::new(served_indexer, served_computer, config.website())?;
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let opt = Some(tokio::spawn(async move {
|
||||
server.serve().await.unwrap();
|
||||
}));
|
||||
let f = move || -> color_eyre::Result<()> {
|
||||
let mut computer = Computer::new(&config.outputsdir(), config.fetcher(), compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs(&indexer, config.computation())?;
|
||||
|
||||
sleep(Duration::from_secs(1));
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()?
|
||||
.block_on(async {
|
||||
let server = if config.serve() {
|
||||
let served_indexer = indexer.clone();
|
||||
let served_computer = computer.clone();
|
||||
|
||||
opt
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let server = Server::new(served_indexer, served_computer, config.website())?;
|
||||
|
||||
if config.process() {
|
||||
let wait_for_synced_node = || -> color_eyre::Result<()> {
|
||||
let is_synced = || -> color_eyre::Result<bool> {
|
||||
let info = rpc.get_blockchain_info()?;
|
||||
Ok(info.headers == info.blocks)
|
||||
};
|
||||
let opt = Some(tokio::spawn(async move {
|
||||
server.serve().await.unwrap();
|
||||
}));
|
||||
|
||||
if !is_synced()? {
|
||||
info!("Waiting for node to be synced...");
|
||||
while !is_synced()? {
|
||||
sleep(Duration::from_secs(1));
|
||||
|
||||
opt
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if config.process() {
|
||||
loop {
|
||||
wait_for_synced_node()?;
|
||||
|
||||
let block_count = rpc.get_block_count()?;
|
||||
|
||||
info!("{} blocks found.", block_count + 1);
|
||||
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
|
||||
computer.compute(&mut indexer, starting_indexes, &exit)?;
|
||||
|
||||
if let Some(delay) = config.delay() {
|
||||
sleep(Duration::from_secs(delay))
|
||||
}
|
||||
|
||||
info!("Waiting for new blocks...");
|
||||
|
||||
while block_count == rpc.get_block_count()? {
|
||||
sleep(Duration::from_secs(1))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
loop {
|
||||
wait_for_synced_node()?;
|
||||
|
||||
let block_count = rpc.get_block_count()?;
|
||||
|
||||
info!("{} blocks found.", block_count + 1);
|
||||
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
|
||||
computer.compute(&mut indexer, starting_indexes, &exit)?;
|
||||
|
||||
if let Some(delay) = config.delay() {
|
||||
sleep(Duration::from_secs(delay))
|
||||
}
|
||||
|
||||
info!("Waiting for new blocks...");
|
||||
|
||||
while block_count == rpc.get_block_count()? {
|
||||
sleep(Duration::from_secs(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(handle) = server {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
if let Some(handle) = server {
|
||||
handle.await.unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
|
||||
thread::Builder::new()
|
||||
.stack_size(128 * 1024 * 1024)
|
||||
.spawn(f)?
|
||||
.join()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]
|
||||
|
||||
@@ -17,7 +17,11 @@ brk_vec = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
clap_derive = { workspace = true }
|
||||
color-eyre = { workspace = true }
|
||||
derive_deref = { workspace = true }
|
||||
fjall = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
zerocopy = { workspace = true }
|
||||
zerocopy-derive = { workspace = true }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::path::Path;
|
||||
use std::{path::Path, thread};
|
||||
|
||||
use brk_computer::Computer;
|
||||
use brk_core::default_bitcoin_path;
|
||||
use brk_core::{default_bitcoin_path, default_brk_path};
|
||||
use brk_exit::Exit;
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
@@ -21,25 +21,34 @@ pub fn main() -> color_eyre::Result<()> {
|
||||
)?));
|
||||
let exit = Exit::new();
|
||||
|
||||
let parser = Parser::new(bitcoin_dir.join("blocks"), rpc);
|
||||
// Can't increase main thread's stack programatically, thus we need to use another thread
|
||||
thread::Builder::new()
|
||||
.stack_size(32 * 1024 * 1024)
|
||||
.spawn(move || -> color_eyre::Result<()> {
|
||||
let parser = Parser::new(bitcoin_dir.join("blocks"), rpc);
|
||||
|
||||
let outputs_dir = Path::new("../../_outputs");
|
||||
let _outputs_dir = default_brk_path().join("outputs");
|
||||
let outputs_dir = _outputs_dir.as_path();
|
||||
// let outputs_dir = Path::new("../../_outputs");
|
||||
|
||||
let compressed = false;
|
||||
let compressed = false;
|
||||
|
||||
let mut indexer = Indexer::new(outputs_dir, compressed, true)?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
let mut indexer = Indexer::new(outputs_dir, compressed, true)?;
|
||||
indexer.import_stores()?;
|
||||
indexer.import_vecs()?;
|
||||
|
||||
let fetcher = Fetcher::import(None)?;
|
||||
let fetcher = Fetcher::import(None)?;
|
||||
|
||||
let mut computer = Computer::new(outputs_dir, Some(fetcher), compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs(&indexer, Computation::Lazy)?;
|
||||
let mut computer = Computer::new(outputs_dir, Some(fetcher), compressed);
|
||||
computer.import_stores(&indexer)?;
|
||||
computer.import_vecs(&indexer, Computation::Lazy)?;
|
||||
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
let starting_indexes = indexer.index(&parser, rpc, &exit)?;
|
||||
|
||||
computer.compute(&mut indexer, starting_indexes, &exit)?;
|
||||
computer.compute(&mut indexer, starting_indexes, &exit)?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
})?
|
||||
.join()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -7,14 +7,18 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use brk_exit::Exit;
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_indexer::{Indexer, Indexes};
|
||||
use brk_indexer::Indexer;
|
||||
pub use brk_parser::rpc;
|
||||
|
||||
mod storage;
|
||||
|
||||
use brk_vec::{AnyCollectableVec, Compressed, Computation};
|
||||
|
||||
mod states;
|
||||
mod stores;
|
||||
mod utils;
|
||||
mod vecs;
|
||||
|
||||
use log::info;
|
||||
use storage::{Stores, Vecs};
|
||||
use stores::Stores;
|
||||
use vecs::Vecs;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Computer {
|
||||
@@ -66,7 +70,7 @@ impl Computer {
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &mut Indexer,
|
||||
starting_indexes: Indexes,
|
||||
starting_indexes: brk_indexer::Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
info!("Computing...");
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use std::ops::{Add, AddAssign, SubAssign};
|
||||
|
||||
use brk_core::{Dollars, Timestamp};
|
||||
|
||||
use super::SupplyState;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BlockState {
|
||||
pub supply: SupplyState,
|
||||
pub price: Option<Dollars>,
|
||||
pub timestamp: Timestamp,
|
||||
}
|
||||
|
||||
impl Add<BlockState> for BlockState {
|
||||
type Output = Self;
|
||||
fn add(mut self, rhs: BlockState) -> Self::Output {
|
||||
self.supply += &rhs.supply;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<&BlockState> for BlockState {
|
||||
fn add_assign(&mut self, rhs: &Self) {
|
||||
self.supply += &rhs.supply;
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<&BlockState> for BlockState {
|
||||
fn sub_assign(&mut self, rhs: &Self) {
|
||||
self.supply -= &rhs.supply;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use brk_core::Dollars;
|
||||
|
||||
use super::{RealizedState, SupplyState};
|
||||
|
||||
// Vecs ? probably
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct CohortState {
|
||||
pub supply: SupplyState,
|
||||
pub realized: Option<RealizedState>,
|
||||
// pub price_to_amount: PriceToValue<Amount>, save it not rounded in fjall
|
||||
}
|
||||
|
||||
impl CohortState {
|
||||
pub fn increment(&mut self, supply_state: &SupplyState, price: Option<Dollars>) {
|
||||
self.supply += supply_state;
|
||||
if let Some(realized) = self.realized.as_mut() {
|
||||
realized.increment(supply_state, price.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrement(&mut self, supply_state: &SupplyState, price: Option<Dollars>) {
|
||||
self.supply -= supply_state;
|
||||
if let Some(realized) = self.realized.as_mut() {
|
||||
realized.decrement(supply_state, price.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
pub struct OneShotSats {
|
||||
pub price_paid_state: PricePaidState,
|
||||
pub unrealized_block_state: UnrealizedState,
|
||||
pub unrealized_date_state: Option<UnrealizedState>,
|
||||
}
|
||||
|
||||
pub struct UnrealizedState {
|
||||
supply_in_profit: Sats,
|
||||
// supply_in_loss: Sats,
|
||||
unrealized_profit: Dollars,
|
||||
unrealized_loss: Dollars,
|
||||
}
|
||||
|
||||
// Why option ?
|
||||
#[derive(Default, Debug)]
|
||||
pub struct PricePaidState {
|
||||
pp_p5: Option<Dollars>,
|
||||
pp_p10: Option<Dollars>,
|
||||
pp_p15: Option<Dollars>,
|
||||
pp_p20: Option<Dollars>,
|
||||
pp_p25: Option<Dollars>,
|
||||
pp_p30: Option<Dollars>,
|
||||
pp_p35: Option<Dollars>,
|
||||
pp_p40: Option<Dollars>,
|
||||
pp_p45: Option<Dollars>,
|
||||
pp_median: Option<Dollars>,
|
||||
pp_p55: Option<Dollars>,
|
||||
pp_p60: Option<Dollars>,
|
||||
pp_p65: Option<Dollars>,
|
||||
pp_p70: Option<Dollars>,
|
||||
pp_p75: Option<Dollars>,
|
||||
pp_p80: Option<Dollars>,
|
||||
pp_p85: Option<Dollars>,
|
||||
pp_p90: Option<Dollars>,
|
||||
pp_p95: Option<Dollars>,
|
||||
|
||||
processed_amount: Sats,
|
||||
}
|
||||
|
||||
pub struct PricePaidStateFull {
|
||||
pp_p1: Option<Dollars>,
|
||||
pp_p2: Option<Dollars>,
|
||||
pp_p3: Option<Dollars>,
|
||||
pp_p4: Option<Dollars>,
|
||||
pp_p5: Option<Dollars>,
|
||||
pp_p6: Option<Dollars>,
|
||||
pp_p7: Option<Dollars>,
|
||||
pp_p8: Option<Dollars>,
|
||||
pp_p9: Option<Dollars>,
|
||||
pp_p10: Option<Dollars>,
|
||||
pp_p11: Option<Dollars>,
|
||||
pp_p12: Option<Dollars>,
|
||||
pp_p13: Option<Dollars>,
|
||||
pp_p14: Option<Dollars>,
|
||||
pp_p15: Option<Dollars>,
|
||||
pp_p16: Option<Dollars>,
|
||||
pp_p17: Option<Dollars>,
|
||||
pp_p18: Option<Dollars>,
|
||||
pp_p19: Option<Dollars>,
|
||||
pp_p20: Option<Dollars>,
|
||||
pp_p21: Option<Dollars>,
|
||||
pp_p22: Option<Dollars>,
|
||||
pp_p23: Option<Dollars>,
|
||||
pp_p24: Option<Dollars>,
|
||||
pp_p25: Option<Dollars>,
|
||||
pp_p26: Option<Dollars>,
|
||||
pp_p27: Option<Dollars>,
|
||||
pp_p28: Option<Dollars>,
|
||||
pp_p29: Option<Dollars>,
|
||||
pp_p30: Option<Dollars>,
|
||||
pp_p31: Option<Dollars>,
|
||||
pp_p32: Option<Dollars>,
|
||||
pp_p33: Option<Dollars>,
|
||||
pp_p34: Option<Dollars>,
|
||||
pp_p35: Option<Dollars>,
|
||||
pp_p36: Option<Dollars>,
|
||||
pp_p37: Option<Dollars>,
|
||||
pp_p38: Option<Dollars>,
|
||||
pp_p39: Option<Dollars>,
|
||||
pp_p40: Option<Dollars>,
|
||||
pp_p41: Option<Dollars>,
|
||||
pp_p42: Option<Dollars>,
|
||||
pp_p43: Option<Dollars>,
|
||||
pp_p44: Option<Dollars>,
|
||||
pp_p45: Option<Dollars>,
|
||||
pp_p46: Option<Dollars>,
|
||||
pp_p47: Option<Dollars>,
|
||||
pp_p48: Option<Dollars>,
|
||||
pp_p49: Option<Dollars>,
|
||||
pp_p50: Option<Dollars>,
|
||||
pp_p51: Option<Dollars>,
|
||||
pp_p52: Option<Dollars>,
|
||||
pp_p53: Option<Dollars>,
|
||||
pp_p54: Option<Dollars>,
|
||||
pp_p55: Option<Dollars>,
|
||||
pp_p56: Option<Dollars>,
|
||||
pp_p57: Option<Dollars>,
|
||||
pp_p58: Option<Dollars>,
|
||||
pp_p59: Option<Dollars>,
|
||||
pp_p60: Option<Dollars>,
|
||||
pp_p61: Option<Dollars>,
|
||||
pp_p62: Option<Dollars>,
|
||||
pp_p63: Option<Dollars>,
|
||||
pp_p64: Option<Dollars>,
|
||||
pp_p65: Option<Dollars>,
|
||||
pp_p66: Option<Dollars>,
|
||||
pp_p67: Option<Dollars>,
|
||||
pp_p68: Option<Dollars>,
|
||||
pp_p69: Option<Dollars>,
|
||||
pp_p70: Option<Dollars>,
|
||||
pp_p71: Option<Dollars>,
|
||||
pp_p72: Option<Dollars>,
|
||||
pp_p73: Option<Dollars>,
|
||||
pp_p74: Option<Dollars>,
|
||||
pp_p75: Option<Dollars>,
|
||||
pp_p76: Option<Dollars>,
|
||||
pp_p77: Option<Dollars>,
|
||||
pp_p78: Option<Dollars>,
|
||||
pp_p79: Option<Dollars>,
|
||||
pp_p80: Option<Dollars>,
|
||||
pp_p81: Option<Dollars>,
|
||||
pp_p82: Option<Dollars>,
|
||||
pp_p83: Option<Dollars>,
|
||||
pp_p84: Option<Dollars>,
|
||||
pp_p85: Option<Dollars>,
|
||||
pp_p86: Option<Dollars>,
|
||||
pp_p87: Option<Dollars>,
|
||||
pp_p88: Option<Dollars>,
|
||||
pp_p89: Option<Dollars>,
|
||||
pp_p90: Option<Dollars>,
|
||||
pp_p91: Option<Dollars>,
|
||||
pp_p92: Option<Dollars>,
|
||||
pp_p93: Option<Dollars>,
|
||||
pp_p94: Option<Dollars>,
|
||||
pp_p95: Option<Dollars>,
|
||||
pp_p96: Option<Dollars>,
|
||||
pp_p97: Option<Dollars>,
|
||||
pp_p98: Option<Dollars>,
|
||||
pp_p99: Option<Dollars>,
|
||||
|
||||
processed_amount: Sats,
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
mod block;
|
||||
mod cohort;
|
||||
mod outputs;
|
||||
mod realized;
|
||||
// mod hot;
|
||||
mod supply;
|
||||
mod transacted;
|
||||
|
||||
pub use block::*;
|
||||
pub use cohort::*;
|
||||
pub use outputs::*;
|
||||
pub use realized::*;
|
||||
// pub use hot::*;
|
||||
pub use supply::*;
|
||||
pub use transacted::*;
|
||||
@@ -0,0 +1,59 @@
|
||||
use brk_core::{HalvingEpoch, Height};
|
||||
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByEpoch<T> {
|
||||
pub _0: T,
|
||||
pub _1: T,
|
||||
pub _2: T,
|
||||
pub _3: T,
|
||||
pub _4: T,
|
||||
}
|
||||
|
||||
impl<T> From<OutputsByEpoch<T>> for OutputsByEpoch<(OutputFilter, T)> {
|
||||
fn from(value: OutputsByEpoch<T>) -> Self {
|
||||
Self {
|
||||
_0: (OutputFilter::Epoch(HalvingEpoch::new(0)), value._0),
|
||||
_1: (OutputFilter::Epoch(HalvingEpoch::new(1)), value._1),
|
||||
_2: (OutputFilter::Epoch(HalvingEpoch::new(2)), value._2),
|
||||
_3: (OutputFilter::Epoch(HalvingEpoch::new(3)), value._3),
|
||||
_4: (OutputFilter::Epoch(HalvingEpoch::new(4)), value._4),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByEpoch<T> {
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 5] {
|
||||
[
|
||||
&mut self._0,
|
||||
&mut self._1,
|
||||
&mut self._2,
|
||||
&mut self._3,
|
||||
&mut self._4,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn mut_vec_from_height(&mut self, height: Height) -> &mut T {
|
||||
let epoch = HalvingEpoch::from(height);
|
||||
if epoch == HalvingEpoch::new(0) {
|
||||
&mut self._0
|
||||
} else if epoch == HalvingEpoch::new(1) {
|
||||
&mut self._1
|
||||
} else if epoch == HalvingEpoch::new(2) {
|
||||
&mut self._2
|
||||
} else if epoch == HalvingEpoch::new(3) {
|
||||
&mut self._3
|
||||
} else if epoch == HalvingEpoch::new(4) {
|
||||
&mut self._4
|
||||
} else {
|
||||
todo!("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByEpoch<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 5] {
|
||||
[&self._0.1, &self._1.1, &self._2.1, &self._3.1, &self._4.1]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByFrom<T> {
|
||||
pub _1d: T,
|
||||
pub _1w: T,
|
||||
pub _1m: T,
|
||||
pub _2m: T,
|
||||
pub _3m: T,
|
||||
pub _4m: T,
|
||||
pub _5m: T,
|
||||
pub _6m: T,
|
||||
pub _1y: T,
|
||||
pub _2y: T,
|
||||
pub _3y: T,
|
||||
pub _4y: T,
|
||||
pub _5y: T,
|
||||
pub _6y: T,
|
||||
pub _7y: T,
|
||||
pub _8y: T,
|
||||
pub _10y: T,
|
||||
pub _15y: T,
|
||||
}
|
||||
|
||||
impl<T> OutputsByFrom<T> {
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 18] {
|
||||
[
|
||||
&mut self._1d,
|
||||
&mut self._1w,
|
||||
&mut self._1m,
|
||||
&mut self._2m,
|
||||
&mut self._3m,
|
||||
&mut self._4m,
|
||||
&mut self._5m,
|
||||
&mut self._6m,
|
||||
&mut self._1y,
|
||||
&mut self._2y,
|
||||
&mut self._3y,
|
||||
&mut self._4y,
|
||||
&mut self._5y,
|
||||
&mut self._6y,
|
||||
&mut self._7y,
|
||||
&mut self._8y,
|
||||
&mut self._10y,
|
||||
&mut self._15y,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByFrom<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 18] {
|
||||
[
|
||||
&self._1d.1,
|
||||
&self._1w.1,
|
||||
&self._1m.1,
|
||||
&self._2m.1,
|
||||
&self._3m.1,
|
||||
&self._4m.1,
|
||||
&self._5m.1,
|
||||
&self._6m.1,
|
||||
&self._1y.1,
|
||||
&self._2y.1,
|
||||
&self._3y.1,
|
||||
&self._4y.1,
|
||||
&self._5y.1,
|
||||
&self._6y.1,
|
||||
&self._7y.1,
|
||||
&self._8y.1,
|
||||
&self._10y.1,
|
||||
&self._15y.1,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<OutputsByFrom<T>> for OutputsByFrom<(OutputFilter, T)> {
|
||||
fn from(value: OutputsByFrom<T>) -> Self {
|
||||
Self {
|
||||
_1d: (OutputFilter::From(1), value._1d),
|
||||
_1w: (OutputFilter::From(7), value._1w),
|
||||
_1m: (OutputFilter::From(30), value._1m),
|
||||
_2m: (OutputFilter::From(2 * 30), value._2m),
|
||||
_3m: (OutputFilter::From(3 * 30), value._3m),
|
||||
_4m: (OutputFilter::From(4 * 30), value._4m),
|
||||
_5m: (OutputFilter::From(5 * 30), value._5m),
|
||||
_6m: (OutputFilter::From(6 * 30), value._6m),
|
||||
_1y: (OutputFilter::From(365), value._1y),
|
||||
_2y: (OutputFilter::From(2 * 365), value._2y),
|
||||
_3y: (OutputFilter::From(3 * 365), value._3y),
|
||||
_4y: (OutputFilter::From(4 * 365), value._4y),
|
||||
_5y: (OutputFilter::From(5 * 365), value._5y),
|
||||
_6y: (OutputFilter::From(6 * 365), value._6y),
|
||||
_7y: (OutputFilter::From(7 * 365), value._7y),
|
||||
_8y: (OutputFilter::From(8 * 365), value._8y),
|
||||
_10y: (OutputFilter::From(10 * 365), value._10y),
|
||||
_15y: (OutputFilter::From(15 * 365), value._15y),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByRange<T> {
|
||||
pub _1d_to_1w: T,
|
||||
pub _1w_to_1m: T,
|
||||
pub _1m_to_3m: T,
|
||||
pub _3m_to_6m: T,
|
||||
pub _6m_to_1y: T,
|
||||
pub _1y_to_2y: T,
|
||||
pub _2y_to_3y: T,
|
||||
pub _3y_to_4y: T,
|
||||
pub _4y_to_5y: T,
|
||||
pub _5y_to_7y: T,
|
||||
pub _7y_to_10y: T,
|
||||
pub _10y_to_15y: T,
|
||||
}
|
||||
|
||||
impl<T> From<OutputsByRange<T>> for OutputsByRange<(OutputFilter, T)> {
|
||||
fn from(value: OutputsByRange<T>) -> Self {
|
||||
Self {
|
||||
_1d_to_1w: (OutputFilter::Range(1..7), value._1d_to_1w),
|
||||
_1w_to_1m: (OutputFilter::Range(7..30), value._1w_to_1m),
|
||||
_1m_to_3m: (OutputFilter::Range(30..3 * 30), value._1m_to_3m),
|
||||
_3m_to_6m: (OutputFilter::Range(3 * 30..6 * 30), value._3m_to_6m),
|
||||
_6m_to_1y: (OutputFilter::Range(6 * 30..365), value._6m_to_1y),
|
||||
_1y_to_2y: (OutputFilter::Range(365..2 * 365), value._1y_to_2y),
|
||||
_2y_to_3y: (OutputFilter::Range(2 * 365..3 * 365), value._2y_to_3y),
|
||||
_3y_to_4y: (OutputFilter::Range(3 * 365..4 * 365), value._3y_to_4y),
|
||||
_4y_to_5y: (OutputFilter::Range(4 * 365..5 * 365), value._4y_to_5y),
|
||||
_5y_to_7y: (OutputFilter::Range(5 * 365..7 * 365), value._5y_to_7y),
|
||||
_7y_to_10y: (OutputFilter::Range(7 * 365..10 * 365), value._7y_to_10y),
|
||||
_10y_to_15y: (OutputFilter::Range(10 * 365..15 * 365), value._10y_to_15y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByRange<T> {
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 12] {
|
||||
[
|
||||
&mut self._1d_to_1w,
|
||||
&mut self._1w_to_1m,
|
||||
&mut self._1m_to_3m,
|
||||
&mut self._3m_to_6m,
|
||||
&mut self._6m_to_1y,
|
||||
&mut self._1y_to_2y,
|
||||
&mut self._2y_to_3y,
|
||||
&mut self._3y_to_4y,
|
||||
&mut self._4y_to_5y,
|
||||
&mut self._5y_to_7y,
|
||||
&mut self._7y_to_10y,
|
||||
&mut self._10y_to_15y,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByRange<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 12] {
|
||||
[
|
||||
&self._1d_to_1w.1,
|
||||
&self._1w_to_1m.1,
|
||||
&self._1m_to_3m.1,
|
||||
&self._3m_to_6m.1,
|
||||
&self._6m_to_1y.1,
|
||||
&self._1y_to_2y.1,
|
||||
&self._2y_to_3y.1,
|
||||
&self._3y_to_4y.1,
|
||||
&self._4y_to_5y.1,
|
||||
&self._5y_to_7y.1,
|
||||
&self._7y_to_10y.1,
|
||||
&self._10y_to_15y.1,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsBySize<T> {
|
||||
pub _0sat: T,
|
||||
pub from_1sat_to_10sats: T,
|
||||
pub from_10sats_to_100sats: T,
|
||||
pub from_100sats_to_1_000sats: T,
|
||||
pub from_1_000sats_to_10_000sats: T,
|
||||
pub from_10_000sats_to_100_000sats: T,
|
||||
pub from_100_000sats_to_1_000_000sats: T,
|
||||
pub from_1_000_000sats_to_10_000_000sats: T,
|
||||
pub from_10_000_000sats_to_1btc: T,
|
||||
pub from_1btc_to_10btc: T,
|
||||
pub from_10btc_to_100btc: T,
|
||||
pub from_100btc_to_1_000btc: T,
|
||||
pub from_1_000btc_to_10_000btc: T,
|
||||
pub from_10_000btc_to_100_000btc: T,
|
||||
pub from_100_000btc: T,
|
||||
}
|
||||
|
||||
impl<T> From<OutputsBySize<T>> for OutputsBySize<(OutputFilter, T)> {
|
||||
fn from(value: OutputsBySize<T>) -> Self {
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
Self {
|
||||
_0sat: (
|
||||
// OutputFilter::Zero,
|
||||
OutputFilter::Size,
|
||||
value._0sat,
|
||||
),
|
||||
from_1sat_to_10sats: (
|
||||
// OutputFilter::Size(Sats::new(1)..Sats::new(10)),
|
||||
OutputFilter::Size,
|
||||
value.from_1sat_to_10sats,
|
||||
),
|
||||
from_10sats_to_100sats: (
|
||||
// OutputFilter::Size(Sats::new(10)..Sats::new(100)),
|
||||
OutputFilter::Size,
|
||||
value.from_10sats_to_100sats,
|
||||
),
|
||||
from_100sats_to_1_000sats: (
|
||||
// OutputFilter::Size(Sats::new(100)..Sats::new(1_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_100sats_to_1_000sats,
|
||||
),
|
||||
from_1_000sats_to_10_000sats: (
|
||||
// OutputFilter::Size(Sats::new(1_000)..Sats::new(10_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_1_000sats_to_10_000sats,
|
||||
),
|
||||
from_10_000sats_to_100_000sats: (
|
||||
// OutputFilter::Size(Sats::new(10_000)..Sats::new(100_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_10_000sats_to_100_000sats,
|
||||
),
|
||||
from_100_000sats_to_1_000_000sats: (
|
||||
// OutputFilter::Size(Sats::new(100_000)..Sats::new(1_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_100_000sats_to_1_000_000sats,
|
||||
),
|
||||
from_1_000_000sats_to_10_000_000sats: (
|
||||
// OutputFilter::Size(Sats::new(1_000_000)..Sats::new(10_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_1_000_000sats_to_10_000_000sats,
|
||||
),
|
||||
from_10_000_000sats_to_1btc: (
|
||||
// OutputFilter::Size(Sats::new(10_000_000)..Sats::new(1_00_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_10_000_000sats_to_1btc,
|
||||
),
|
||||
from_1btc_to_10btc: (
|
||||
// OutputFilter::Size(Sats::new(1_00_000_000)..Sats::new(10_00_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_1btc_to_10btc,
|
||||
),
|
||||
from_10btc_to_100btc: (
|
||||
// OutputFilter::Size(Sats::new(10_00_000_000)..Sats::new(100_00_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_10btc_to_100btc,
|
||||
),
|
||||
from_100btc_to_1_000btc: (
|
||||
// OutputFilter::Size(Sats::new(100_00_000_000)..Sats::new(1_000_00_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_100btc_to_1_000btc,
|
||||
),
|
||||
from_1_000btc_to_10_000btc: (
|
||||
// OutputFilter::Size(Sats::new(1_000_00_000_000)..Sats::new(10_000_00_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_1_000btc_to_10_000btc,
|
||||
),
|
||||
from_10_000btc_to_100_000btc: (
|
||||
// OutputFilter::Size(Sats::new(10_000_00_000_000)..Sats::new(100_000_00_000_000)),
|
||||
OutputFilter::Size,
|
||||
value.from_10_000btc_to_100_000btc,
|
||||
),
|
||||
from_100_000btc: (
|
||||
// OutputFilter::Size(Sats::new(100_000_00_000_000)..Sats::MAX),
|
||||
OutputFilter::Size,
|
||||
value.from_100_000btc,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsBySize<T> {
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
pub fn get_mut(&mut self, group: usize) -> &mut T {
|
||||
if group == 0 {
|
||||
&mut self._0sat
|
||||
} else if group == 10 {
|
||||
&mut self.from_1sat_to_10sats
|
||||
} else if group == 100 {
|
||||
&mut self.from_10sats_to_100sats
|
||||
} else if group == 1_000 {
|
||||
&mut self.from_100sats_to_1_000sats
|
||||
} else if group == 10_000 {
|
||||
&mut self.from_1_000sats_to_10_000sats
|
||||
} else if group == 100_000 {
|
||||
&mut self.from_10_000sats_to_100_000sats
|
||||
} else if group == 1_000_000 {
|
||||
&mut self.from_100_000sats_to_1_000_000sats
|
||||
} else if group == 10_000_000 {
|
||||
&mut self.from_1_000_000sats_to_10_000_000sats
|
||||
} else if group == 1_00_000_000 {
|
||||
&mut self.from_10_000_000sats_to_1btc
|
||||
} else if group == 10_00_000_000 {
|
||||
&mut self.from_1btc_to_10btc
|
||||
} else if group == 100_00_000_000 {
|
||||
&mut self.from_10btc_to_100btc
|
||||
} else if group == 1_000_00_000_000 {
|
||||
&mut self.from_100btc_to_1_000btc
|
||||
} else if group == 10_000_00_000_000 {
|
||||
&mut self.from_1_000btc_to_10_000btc
|
||||
} else if group == 100_000_00_000_000 {
|
||||
&mut self.from_10_000btc_to_100_000btc
|
||||
} else {
|
||||
&mut self.from_100_000btc
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 15] {
|
||||
[
|
||||
&mut self._0sat,
|
||||
&mut self.from_1sat_to_10sats,
|
||||
&mut self.from_10sats_to_100sats,
|
||||
&mut self.from_100sats_to_1_000sats,
|
||||
&mut self.from_1_000sats_to_10_000sats,
|
||||
&mut self.from_10_000sats_to_100_000sats,
|
||||
&mut self.from_100_000sats_to_1_000_000sats,
|
||||
&mut self.from_1_000_000sats_to_10_000_000sats,
|
||||
&mut self.from_10_000_000sats_to_1btc,
|
||||
&mut self.from_1btc_to_10btc,
|
||||
&mut self.from_10btc_to_100btc,
|
||||
&mut self.from_100btc_to_1_000btc,
|
||||
&mut self.from_1_000btc_to_10_000btc,
|
||||
&mut self.from_10_000btc_to_100_000btc,
|
||||
&mut self.from_100_000btc,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsBySize<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 15] {
|
||||
[
|
||||
&self._0sat.1,
|
||||
&self.from_1sat_to_10sats.1,
|
||||
&self.from_10sats_to_100sats.1,
|
||||
&self.from_100sats_to_1_000sats.1,
|
||||
&self.from_1_000sats_to_10_000sats.1,
|
||||
&self.from_10_000sats_to_100_000sats.1,
|
||||
&self.from_100_000sats_to_1_000_000sats.1,
|
||||
&self.from_1_000_000sats_to_10_000_000sats.1,
|
||||
&self.from_10_000_000sats_to_1btc.1,
|
||||
&self.from_1btc_to_10btc.1,
|
||||
&self.from_10btc_to_100btc.1,
|
||||
&self.from_100btc_to_1_000btc.1,
|
||||
&self.from_1_000btc_to_10_000btc.1,
|
||||
&self.from_10_000btc_to_100_000btc.1,
|
||||
&self.from_100_000btc.1,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
use brk_core::OutputType;
|
||||
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsBySpendableType<T> {
|
||||
pub p2pk65: T,
|
||||
pub p2pk33: T,
|
||||
pub p2pkh: T,
|
||||
pub p2ms: T,
|
||||
pub p2sh: T,
|
||||
pub p2wpkh: T,
|
||||
pub p2wsh: T,
|
||||
pub p2tr: T,
|
||||
pub p2a: T,
|
||||
pub unknown: T,
|
||||
pub empty: T,
|
||||
}
|
||||
|
||||
impl<T> OutputsBySpendableType<T> {
|
||||
// pub fn get(&self, output_type: OutputType) -> &T {
|
||||
// match output_type {
|
||||
// OutputType::P2PK65 => &self.p2pk65,
|
||||
// OutputType::P2PK33 => &self.p2pk33,
|
||||
// OutputType::P2PKH => &self.p2pkh,
|
||||
// OutputType::P2MS => &self.p2ms,
|
||||
// OutputType::P2SH => &self.p2sh,
|
||||
// OutputType::P2WPKH => &self.p2wpkh,
|
||||
// OutputType::P2WSH => &self.p2wsh,
|
||||
// OutputType::P2TR => &self.p2tr,
|
||||
// OutputType::P2A => &self.p2a,
|
||||
// OutputType::Unknown => &self.unknown,
|
||||
// OutputType::Empty => &self.empty,
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
||||
match output_type {
|
||||
OutputType::P2PK65 => &mut self.p2pk65,
|
||||
OutputType::P2PK33 => &mut self.p2pk33,
|
||||
OutputType::P2PKH => &mut self.p2pkh,
|
||||
OutputType::P2MS => &mut self.p2ms,
|
||||
OutputType::P2SH => &mut self.p2sh,
|
||||
OutputType::P2WPKH => &mut self.p2wpkh,
|
||||
OutputType::P2WSH => &mut self.p2wsh,
|
||||
OutputType::P2TR => &mut self.p2tr,
|
||||
OutputType::P2A => &mut self.p2a,
|
||||
OutputType::Unknown => &mut self.unknown,
|
||||
OutputType::Empty => &mut self.empty,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn as_vec(&self) -> [&T; 11] {
|
||||
// [
|
||||
// &self.p2pk65,
|
||||
// &self.p2pk33,
|
||||
// &self.p2pkh,
|
||||
// &self.p2ms,
|
||||
// &self.p2sh,
|
||||
// &self.p2wpkh,
|
||||
// &self.p2wsh,
|
||||
// &self.p2tr,
|
||||
// &self.p2a,
|
||||
// &self.unknown,
|
||||
// &self.empty,
|
||||
// ]
|
||||
// }
|
||||
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 11] {
|
||||
[
|
||||
&mut self.p2pk65,
|
||||
&mut self.p2pk33,
|
||||
&mut self.p2pkh,
|
||||
&mut self.p2ms,
|
||||
&mut self.p2sh,
|
||||
&mut self.p2wpkh,
|
||||
&mut self.p2wsh,
|
||||
&mut self.p2tr,
|
||||
&mut self.p2a,
|
||||
&mut self.unknown,
|
||||
&mut self.empty,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn as_typed_vec(&self) -> [(OutputType, &T); 11] {
|
||||
[
|
||||
(OutputType::P2PK65, &self.p2pk65),
|
||||
(OutputType::P2PK33, &self.p2pk33),
|
||||
(OutputType::P2PKH, &self.p2pkh),
|
||||
(OutputType::P2MS, &self.p2ms),
|
||||
(OutputType::P2SH, &self.p2sh),
|
||||
(OutputType::P2WPKH, &self.p2wpkh),
|
||||
(OutputType::P2WSH, &self.p2wsh),
|
||||
(OutputType::P2TR, &self.p2tr),
|
||||
(OutputType::P2A, &self.p2a),
|
||||
(OutputType::Unknown, &self.unknown),
|
||||
(OutputType::Empty, &self.empty),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsBySpendableType<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 11] {
|
||||
[
|
||||
&self.p2pk65.1,
|
||||
&self.p2pk33.1,
|
||||
&self.p2pkh.1,
|
||||
&self.p2ms.1,
|
||||
&self.p2sh.1,
|
||||
&self.p2wpkh.1,
|
||||
&self.p2wsh.1,
|
||||
&self.p2tr.1,
|
||||
&self.p2a.1,
|
||||
&self.unknown.1,
|
||||
&self.empty.1,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<OutputsBySpendableType<T>> for OutputsBySpendableType<(OutputFilter, T)> {
|
||||
fn from(value: OutputsBySpendableType<T>) -> Self {
|
||||
Self {
|
||||
p2pk65: (OutputFilter::Type(OutputType::P2PK65), value.p2pk65),
|
||||
p2pk33: (OutputFilter::Type(OutputType::P2PK33), value.p2pk33),
|
||||
p2pkh: (OutputFilter::Type(OutputType::P2PKH), value.p2pkh),
|
||||
p2ms: (OutputFilter::Type(OutputType::P2MS), value.p2ms),
|
||||
p2sh: (OutputFilter::Type(OutputType::P2SH), value.p2sh),
|
||||
p2wpkh: (OutputFilter::Type(OutputType::P2WPKH), value.p2wpkh),
|
||||
p2wsh: (OutputFilter::Type(OutputType::P2WSH), value.p2wsh),
|
||||
p2tr: (OutputFilter::Type(OutputType::P2TR), value.p2tr),
|
||||
p2a: (OutputFilter::Type(OutputType::P2A), value.p2a),
|
||||
unknown: (OutputFilter::Type(OutputType::Unknown), value.unknown),
|
||||
empty: (OutputFilter::Type(OutputType::Empty), value.empty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add for OutputsBySpendableType<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
p2pk65: self.p2pk65 + rhs.p2pk65,
|
||||
p2pk33: self.p2pk33 + rhs.p2pk33,
|
||||
p2pkh: self.p2pkh + rhs.p2pkh,
|
||||
p2ms: self.p2ms + rhs.p2ms,
|
||||
p2sh: self.p2sh + rhs.p2sh,
|
||||
p2wpkh: self.p2wpkh + rhs.p2wpkh,
|
||||
p2wsh: self.p2wsh + rhs.p2wsh,
|
||||
p2tr: self.p2tr + rhs.p2tr,
|
||||
p2a: self.p2a + rhs.p2a,
|
||||
unknown: self.unknown + rhs.unknown,
|
||||
empty: self.empty + rhs.empty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for OutputsBySpendableType<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.p2pk65 += rhs.p2pk65;
|
||||
self.p2pk33 += rhs.p2pk33;
|
||||
self.p2pkh += rhs.p2pkh;
|
||||
self.p2ms += rhs.p2ms;
|
||||
self.p2sh += rhs.p2sh;
|
||||
self.p2wpkh += rhs.p2wpkh;
|
||||
self.p2wsh += rhs.p2wsh;
|
||||
self.p2tr += rhs.p2tr;
|
||||
self.p2a += rhs.p2a;
|
||||
self.unknown += rhs.unknown;
|
||||
self.empty += rhs.empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByTerm<T> {
|
||||
pub short: T,
|
||||
pub long: T,
|
||||
}
|
||||
|
||||
impl<T> OutputsByTerm<T> {
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 2] {
|
||||
[&mut self.short, &mut self.long]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByTerm<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 2] {
|
||||
[&self.short.1, &self.long.1]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<OutputsByTerm<T>> for OutputsByTerm<(OutputFilter, T)> {
|
||||
fn from(value: OutputsByTerm<T>) -> Self {
|
||||
Self {
|
||||
long: (OutputFilter::From(155), value.long),
|
||||
short: (OutputFilter::To(155), value.short),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
use brk_core::OutputType;
|
||||
|
||||
use super::{OutputsBySpendableType, OutputsByUnspendableType};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByType<T> {
|
||||
pub spendable: OutputsBySpendableType<T>,
|
||||
pub unspendable: OutputsByUnspendableType<T>,
|
||||
}
|
||||
|
||||
impl<T> OutputsByType<T> {
|
||||
pub fn get(&self, output_type: OutputType) -> &T {
|
||||
match output_type {
|
||||
OutputType::P2PK65 => &self.spendable.p2pk65,
|
||||
OutputType::P2PK33 => &self.spendable.p2pk33,
|
||||
OutputType::P2PKH => &self.spendable.p2pkh,
|
||||
OutputType::P2MS => &self.spendable.p2ms,
|
||||
OutputType::P2SH => &self.spendable.p2sh,
|
||||
OutputType::P2WPKH => &self.spendable.p2wpkh,
|
||||
OutputType::P2WSH => &self.spendable.p2wsh,
|
||||
OutputType::P2TR => &self.spendable.p2tr,
|
||||
OutputType::P2A => &self.spendable.p2a,
|
||||
OutputType::Empty => &self.spendable.empty,
|
||||
OutputType::Unknown => &self.spendable.unknown,
|
||||
OutputType::OpReturn => &self.unspendable.op_return,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
|
||||
match output_type {
|
||||
OutputType::P2PK65 => &mut self.spendable.p2pk65,
|
||||
OutputType::P2PK33 => &mut self.spendable.p2pk33,
|
||||
OutputType::P2PKH => &mut self.spendable.p2pkh,
|
||||
OutputType::P2MS => &mut self.spendable.p2ms,
|
||||
OutputType::P2SH => &mut self.spendable.p2sh,
|
||||
OutputType::P2WPKH => &mut self.spendable.p2wpkh,
|
||||
OutputType::P2WSH => &mut self.spendable.p2wsh,
|
||||
OutputType::P2TR => &mut self.spendable.p2tr,
|
||||
OutputType::P2A => &mut self.spendable.p2a,
|
||||
OutputType::Unknown => &mut self.spendable.unknown,
|
||||
OutputType::Empty => &mut self.spendable.empty,
|
||||
OutputType::OpReturn => &mut self.unspendable.op_return,
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn as_vec(&self) -> Vec<&T> {
|
||||
// self.spendable
|
||||
// .as_vec()
|
||||
// .into_iter()
|
||||
// .chain(self.unspendable.as_vec())
|
||||
// .collect::<Vec<_>>()
|
||||
// }
|
||||
|
||||
// pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
|
||||
// self.spendable
|
||||
// .as_mut_vec()
|
||||
// .into_iter()
|
||||
// .chain(self.unspendable.as_mut_vec())
|
||||
// .collect::<Vec<_>>()
|
||||
// }
|
||||
}
|
||||
|
||||
impl<T> Add for OutputsByType<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
spendable: self.spendable + rhs.spendable,
|
||||
unspendable: self.unspendable + rhs.unspendable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for OutputsByType<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.spendable += rhs.spendable;
|
||||
self.unspendable += rhs.unspendable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByUnspendableType<T> {
|
||||
pub op_return: T,
|
||||
}
|
||||
|
||||
impl<T> OutputsByUnspendableType<T> {
|
||||
pub fn as_vec(&self) -> [&T; 1] {
|
||||
[&self.op_return]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add for OutputsByUnspendableType<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
op_return: self.op_return + rhs.op_return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for OutputsByUnspendableType<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.op_return += rhs.op_return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
use super::OutputFilter;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByUpTo<T> {
|
||||
pub _1d: T,
|
||||
pub _1w: T,
|
||||
pub _1m: T,
|
||||
pub _2m: T,
|
||||
pub _3m: T,
|
||||
pub _4m: T,
|
||||
pub _5m: T,
|
||||
pub _6m: T,
|
||||
pub _1y: T,
|
||||
pub _2y: T,
|
||||
pub _3y: T,
|
||||
pub _4y: T,
|
||||
pub _5y: T,
|
||||
pub _6y: T,
|
||||
pub _7y: T,
|
||||
pub _8y: T,
|
||||
pub _10y: T,
|
||||
pub _15y: T,
|
||||
}
|
||||
|
||||
impl<T> OutputsByUpTo<T> {
|
||||
pub fn as_mut_vec(&mut self) -> [&mut T; 18] {
|
||||
[
|
||||
&mut self._1d,
|
||||
&mut self._1w,
|
||||
&mut self._1m,
|
||||
&mut self._2m,
|
||||
&mut self._3m,
|
||||
&mut self._4m,
|
||||
&mut self._5m,
|
||||
&mut self._6m,
|
||||
&mut self._1y,
|
||||
&mut self._2y,
|
||||
&mut self._3y,
|
||||
&mut self._4y,
|
||||
&mut self._5y,
|
||||
&mut self._6y,
|
||||
&mut self._7y,
|
||||
&mut self._8y,
|
||||
&mut self._10y,
|
||||
&mut self._15y,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OutputsByUpTo<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> [&T; 18] {
|
||||
[
|
||||
&self._1d.1,
|
||||
&self._1w.1,
|
||||
&self._1m.1,
|
||||
&self._2m.1,
|
||||
&self._3m.1,
|
||||
&self._4m.1,
|
||||
&self._5m.1,
|
||||
&self._6m.1,
|
||||
&self._1y.1,
|
||||
&self._2y.1,
|
||||
&self._3y.1,
|
||||
&self._4y.1,
|
||||
&self._5y.1,
|
||||
&self._6y.1,
|
||||
&self._7y.1,
|
||||
&self._8y.1,
|
||||
&self._10y.1,
|
||||
&self._15y.1,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<OutputsByUpTo<T>> for OutputsByUpTo<(OutputFilter, T)> {
|
||||
fn from(value: OutputsByUpTo<T>) -> Self {
|
||||
Self {
|
||||
_1d: (OutputFilter::To(1), value._1d),
|
||||
_1w: (OutputFilter::To(7), value._1w),
|
||||
_1m: (OutputFilter::To(30), value._1m),
|
||||
_2m: (OutputFilter::To(2 * 30), value._2m),
|
||||
_3m: (OutputFilter::To(3 * 30), value._3m),
|
||||
_4m: (OutputFilter::To(4 * 30), value._4m),
|
||||
_5m: (OutputFilter::To(5 * 30), value._5m),
|
||||
_6m: (OutputFilter::To(6 * 30), value._6m),
|
||||
_1y: (OutputFilter::To(365), value._1y),
|
||||
_2y: (OutputFilter::To(2 * 365), value._2y),
|
||||
_3y: (OutputFilter::To(3 * 365), value._3y),
|
||||
_4y: (OutputFilter::To(4 * 365), value._4y),
|
||||
_5y: (OutputFilter::To(5 * 365), value._5y),
|
||||
_6y: (OutputFilter::To(6 * 365), value._6y),
|
||||
_7y: (OutputFilter::To(7 * 365), value._7y),
|
||||
_8y: (OutputFilter::To(8 * 365), value._8y),
|
||||
_10y: (OutputFilter::To(10 * 365), value._10y),
|
||||
_15y: (OutputFilter::To(15 * 365), value._15y),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OutputsByValue<T> {
|
||||
pub up_to_1cent: T,
|
||||
pub from_1c_to_10c: T,
|
||||
pub from_10c_to_1d: T,
|
||||
pub from_1d_to_10d: T,
|
||||
pub from_10usd_to_100usd: T,
|
||||
pub from_100usd_to_1_000usd: T,
|
||||
pub from_1_000usd_to_10_000usd: T,
|
||||
pub from_10_000usd_to_100_000usd: T,
|
||||
pub from_100_000usd_to_1_000_000usd: T,
|
||||
pub from_1_000_000usd_to_10_000_000usd: T,
|
||||
pub from_10_000_000usd_to_100_000_000usd: T,
|
||||
pub from_100_000_000usd_to_1_000_000_000usd: T,
|
||||
pub from_1_000_000_000usd: T,
|
||||
// ...
|
||||
}
|
||||
|
||||
impl<T> OutputsByValue<T> {
|
||||
pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
|
||||
vec![
|
||||
&mut self.up_to_1cent,
|
||||
&mut self.from_1c_to_10c,
|
||||
&mut self.from_10c_to_1d,
|
||||
&mut self.from_1d_to_10d,
|
||||
&mut self.from_10usd_to_100usd,
|
||||
&mut self.from_100usd_to_1_000usd,
|
||||
&mut self.from_1_000usd_to_10_000usd,
|
||||
&mut self.from_10_000usd_to_100_000usd,
|
||||
&mut self.from_100_000usd_to_1_000_000usd,
|
||||
&mut self.from_1_000_000usd_to_10_000_000usd,
|
||||
&mut self.from_10_000_000usd_to_100_000_000usd,
|
||||
&mut self.from_100_000_000usd_to_1_000_000_000usd,
|
||||
&mut self.from_1_000_000_000usd,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use brk_core::{HalvingEpoch, OutputType};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum OutputFilter {
|
||||
All,
|
||||
To(usize),
|
||||
Range(Range<usize>),
|
||||
From(usize),
|
||||
Size,
|
||||
Epoch(HalvingEpoch),
|
||||
Type(OutputType),
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
use brk_vec::StoredIndex;
|
||||
use rayon::prelude::*;
|
||||
use std::{collections::BTreeMap, ops::ControlFlow};
|
||||
|
||||
use brk_core::{Dollars, HalvingEpoch, Height, Timestamp};
|
||||
|
||||
mod by_epoch;
|
||||
mod by_from;
|
||||
mod by_range;
|
||||
mod by_size;
|
||||
mod by_spendable_type;
|
||||
mod by_term;
|
||||
mod by_type;
|
||||
mod by_unspendable_type;
|
||||
mod by_up_to;
|
||||
// mod by_value;
|
||||
mod filter;
|
||||
|
||||
pub use by_epoch::*;
|
||||
pub use by_from::*;
|
||||
pub use by_range::*;
|
||||
pub use by_size::*;
|
||||
pub use by_spendable_type::*;
|
||||
pub use by_term::*;
|
||||
pub use by_type::*;
|
||||
pub use by_unspendable_type::*;
|
||||
pub use by_up_to::*;
|
||||
// pub use by_value::*;
|
||||
pub use filter::*;
|
||||
|
||||
use crate::vecs;
|
||||
|
||||
use super::{BlockState, Transacted};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Outputs<T> {
|
||||
pub all: T,
|
||||
pub by_term: OutputsByTerm<T>,
|
||||
pub by_up_to: OutputsByUpTo<T>,
|
||||
pub by_from: OutputsByFrom<T>,
|
||||
pub by_range: OutputsByRange<T>,
|
||||
pub by_epoch: OutputsByEpoch<T>,
|
||||
pub by_type: OutputsBySpendableType<T>,
|
||||
pub by_size: OutputsBySize<T>,
|
||||
// // Needs whole UTXO set, TODO later
|
||||
// // pub by_value: OutputsByValue<T>,
|
||||
}
|
||||
|
||||
impl<T> Outputs<T> {
|
||||
pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
|
||||
[&mut self.all]
|
||||
.into_iter()
|
||||
.chain(self.by_term.as_mut_vec())
|
||||
.chain(self.by_up_to.as_mut_vec())
|
||||
.chain(self.by_from.as_mut_vec())
|
||||
.chain(self.by_range.as_mut_vec())
|
||||
.chain(self.by_epoch.as_mut_vec())
|
||||
.chain(self.by_size.as_mut_vec())
|
||||
.chain(self.by_type.as_mut_vec())
|
||||
// // .chain(self.by_value.as_mut_vec())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Outputs<(OutputFilter, vecs::utxos::cohort::Vecs)> {
|
||||
pub fn tick_tock_next_block(&mut self, chain_state: &[BlockState], timestamp: Timestamp) {
|
||||
if chain_state.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let prev_timestamp = chain_state.last().unwrap().timestamp;
|
||||
|
||||
self.by_term
|
||||
.as_mut_vec()
|
||||
.into_par_iter()
|
||||
.chain(self.by_up_to.as_mut_vec())
|
||||
.chain(self.by_from.as_mut_vec())
|
||||
.chain(self.by_range.as_mut_vec())
|
||||
.for_each(|(filter, v)| {
|
||||
let state = &mut v.state;
|
||||
|
||||
let mut check_days_old = |days_old: usize| -> bool {
|
||||
match filter {
|
||||
OutputFilter::From(from) => *from <= days_old,
|
||||
OutputFilter::To(to) => *to > days_old,
|
||||
OutputFilter::Range(range) => range.contains(&days_old),
|
||||
OutputFilter::All
|
||||
| OutputFilter::Epoch(_)
|
||||
| OutputFilter::Size
|
||||
| OutputFilter::Type(_) => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
let _ = chain_state
|
||||
.iter()
|
||||
.try_for_each(|block_state| -> ControlFlow<()> {
|
||||
let prev_days_old = block_state
|
||||
.timestamp
|
||||
.difference_in_days_between(prev_timestamp);
|
||||
let days_old = block_state.timestamp.difference_in_days_between(timestamp);
|
||||
|
||||
if prev_days_old == days_old {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
let is = check_days_old(days_old);
|
||||
let was = check_days_old(prev_days_old);
|
||||
|
||||
if is && !was {
|
||||
state.increment(&block_state.supply, block_state.price);
|
||||
} else if was && !is {
|
||||
state.decrement(&block_state.supply, block_state.price);
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send(
|
||||
&mut self,
|
||||
height_to_sent: BTreeMap<Height, Transacted>,
|
||||
chain_state: &[BlockState],
|
||||
) {
|
||||
let mut time_based_vecs = self
|
||||
.by_term
|
||||
.as_mut_vec()
|
||||
.into_iter()
|
||||
.chain(self.by_up_to.as_mut_vec())
|
||||
.chain(self.by_from.as_mut_vec())
|
||||
.chain(self.by_range.as_mut_vec())
|
||||
.chain(self.by_epoch.as_mut_vec())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let last_timestamp = chain_state.last().unwrap().timestamp;
|
||||
|
||||
height_to_sent.into_iter().for_each(|(height, sent)| {
|
||||
let block_state = chain_state.get(height.unwrap_to_usize()).unwrap();
|
||||
let price = block_state.price;
|
||||
|
||||
let days_old = block_state
|
||||
.timestamp
|
||||
.difference_in_days_between(last_timestamp);
|
||||
|
||||
self.all.1.state.decrement(&sent.spendable_supply, price);
|
||||
|
||||
time_based_vecs
|
||||
.iter_mut()
|
||||
.filter(|(filter, _)| match filter {
|
||||
OutputFilter::From(from) => *from <= days_old,
|
||||
OutputFilter::To(to) => *to > days_old,
|
||||
OutputFilter::Range(range) => range.contains(&days_old),
|
||||
OutputFilter::Epoch(epoch) => *epoch == HalvingEpoch::from(height),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.for_each(|(_, vecs)| {
|
||||
vecs.state.decrement(&sent.spendable_supply, price);
|
||||
});
|
||||
|
||||
sent.by_type.spendable.as_typed_vec().into_iter().for_each(
|
||||
|(output_type, supply_state)| {
|
||||
self.by_type
|
||||
.get_mut(output_type)
|
||||
.1
|
||||
.state
|
||||
.decrement(supply_state, price)
|
||||
},
|
||||
);
|
||||
|
||||
sent.by_size.into_iter().for_each(|(group, supply_state)| {
|
||||
self.by_size
|
||||
.get_mut(group)
|
||||
.1
|
||||
.state
|
||||
.decrement(&supply_state, price);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn receive(&mut self, received: Transacted, height: Height, price: Option<Dollars>) {
|
||||
let supply_state = received.spendable_supply;
|
||||
|
||||
[
|
||||
&mut self.all.1,
|
||||
&mut self.by_term.short.1,
|
||||
&mut self.by_epoch.mut_vec_from_height(height).1,
|
||||
// Skip from and range as can't receive in the past
|
||||
]
|
||||
.into_iter()
|
||||
.chain(self.by_up_to.as_mut_vec().map(|(_, v)| v))
|
||||
.for_each(|v| {
|
||||
v.state.increment(&supply_state, price);
|
||||
});
|
||||
|
||||
self.by_type
|
||||
.as_mut_vec()
|
||||
.into_iter()
|
||||
.for_each(|(filter, vecs)| {
|
||||
let output_type = match filter {
|
||||
OutputFilter::Type(output_type) => *output_type,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
vecs.state
|
||||
.increment(received.by_type.get(output_type), price)
|
||||
});
|
||||
|
||||
received
|
||||
.by_size
|
||||
.into_iter()
|
||||
.for_each(|(group, supply_state)| {
|
||||
self.by_size
|
||||
.get_mut(group)
|
||||
.1
|
||||
.state
|
||||
.increment(&supply_state, price);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Outputs<(OutputFilter, T)> {
|
||||
pub fn vecs(&self) -> Vec<&T> {
|
||||
[&self.all.1]
|
||||
.into_iter()
|
||||
.chain(self.by_term.vecs())
|
||||
.chain(self.by_up_to.vecs())
|
||||
.chain(self.by_from.vecs())
|
||||
.chain(self.by_range.vecs())
|
||||
.chain(self.by_epoch.vecs())
|
||||
.chain(self.by_size.vecs())
|
||||
// // .chain(self.by_value.vecs())
|
||||
.chain(self.by_type.vecs())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Outputs<T>> for Outputs<(OutputFilter, T)> {
|
||||
fn from(value: Outputs<T>) -> Self {
|
||||
Self {
|
||||
all: (OutputFilter::All, value.all),
|
||||
by_term: OutputsByTerm::from(value.by_term),
|
||||
by_up_to: OutputsByUpTo::from(value.by_up_to),
|
||||
by_from: OutputsByFrom::from(value.by_from),
|
||||
by_range: OutputsByRange::from(value.by_range),
|
||||
by_epoch: OutputsByEpoch::from(value.by_epoch),
|
||||
by_size: OutputsBySize::from(value.by_size),
|
||||
// // Needs whole UTXO set, TODO later
|
||||
// // by_value: OutputsByValue<T>,
|
||||
by_type: OutputsBySpendableType::from(value.by_type),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
use brk_core::{Bitcoin, CheckedSub, Dollars};
|
||||
|
||||
use super::SupplyState;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct RealizedState {
|
||||
pub realized_cap: Dollars,
|
||||
// pub realized_profit: Dollars,
|
||||
// pub realized_loss: Dollars,
|
||||
// pub value_created: Dollars,
|
||||
// pub adjusted_value_created: Dollars,
|
||||
// pub value_destroyed: Dollars,
|
||||
// pub adjusted_value_destroyed: Dollars,
|
||||
}
|
||||
|
||||
impl RealizedState {
|
||||
pub const NAN: Self = Self {
|
||||
realized_cap: Dollars::NAN,
|
||||
// realized_profit: Dollars::NAN,
|
||||
// realized_loss: Dollars::NAN,
|
||||
// value_created: Dollars::NAN,
|
||||
// adjusted_value_created: Dollars::NAN,
|
||||
// value_destroyed: Dollars::NAN,
|
||||
// adjusted_value_destroyed: Dollars::NAN,
|
||||
};
|
||||
|
||||
pub fn increment(&mut self, supply_state: &SupplyState, price: Dollars) {
|
||||
if supply_state.value.is_not_zero() {
|
||||
if self.realized_cap == Dollars::NAN {
|
||||
self.realized_cap = Dollars::ZERO;
|
||||
// self.realized_profit = Dollars::ZERO;
|
||||
// self.realized_loss = Dollars::ZERO;
|
||||
// self.value_created = Dollars::ZERO;
|
||||
// self.adjusted_value_created = Dollars::ZERO;
|
||||
// self.value_destroyed = Dollars::ZERO;
|
||||
// self.adjusted_value_destroyed = Dollars::ZERO;
|
||||
}
|
||||
|
||||
self.realized_cap += price * Bitcoin::from(supply_state.value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrement(&mut self, supply_state: &SupplyState, price: Dollars) {
|
||||
self.realized_cap = self
|
||||
.realized_cap
|
||||
.checked_sub(price * Bitcoin::from(supply_state.value))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use std::ops::{Add, AddAssign, SubAssign};
|
||||
|
||||
use brk_core::{CheckedSub, Sats};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize)]
|
||||
pub struct SupplyState {
|
||||
pub utxos: usize,
|
||||
pub value: Sats,
|
||||
}
|
||||
|
||||
impl Add<SupplyState> for SupplyState {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: SupplyState) -> Self::Output {
|
||||
Self {
|
||||
utxos: self.utxos + rhs.utxos,
|
||||
value: self.value + rhs.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<SupplyState> for SupplyState {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self += &rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<&SupplyState> for SupplyState {
|
||||
fn add_assign(&mut self, rhs: &Self) {
|
||||
self.utxos += rhs.utxos;
|
||||
self.value += rhs.value;
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<&SupplyState> for SupplyState {
|
||||
fn sub_assign(&mut self, rhs: &Self) {
|
||||
self.utxos = self.utxos.checked_sub(rhs.utxos).unwrap();
|
||||
self.value = self.value.checked_sub(rhs.value).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
mem,
|
||||
ops::{Add, AddAssign},
|
||||
};
|
||||
|
||||
use brk_core::{OutputType, Sats};
|
||||
|
||||
use super::{OutputsByType, SupplyState};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Transacted {
|
||||
pub spendable_supply: SupplyState,
|
||||
pub by_type: OutputsByType<SupplyState>,
|
||||
pub by_size: BTreeMap<usize, SupplyState>,
|
||||
}
|
||||
|
||||
impl Transacted {
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
pub fn iterate(&mut self, value: Sats, _type: OutputType) {
|
||||
let supply = SupplyState { utxos: 1, value };
|
||||
|
||||
*self.by_type.get_mut(_type) += &supply;
|
||||
|
||||
if _type.is_unspendable() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.spendable_supply += &supply;
|
||||
|
||||
let _value = usize::from(value);
|
||||
|
||||
// Need to be in sync with by_size !! but plenty fast (I think)
|
||||
if _value == 0 {
|
||||
*self.by_size.entry(0).or_default() += &supply;
|
||||
} else if _value < 10 {
|
||||
*self.by_size.entry(1).or_default() += &supply;
|
||||
} else if _value < 100 {
|
||||
*self.by_size.entry(10).or_default() += &supply;
|
||||
} else if _value < 1_000 {
|
||||
*self.by_size.entry(100).or_default() += &supply;
|
||||
} else if _value < 10_000 {
|
||||
*self.by_size.entry(1_000).or_default() += &supply;
|
||||
} else if _value < 100_000 {
|
||||
*self.by_size.entry(10_000).or_default() += &supply;
|
||||
} else if _value < 1_000_000 {
|
||||
*self.by_size.entry(100_000).or_default() += &supply;
|
||||
} else if _value < 10_000_000 {
|
||||
*self.by_size.entry(1_000_000).or_default() += &supply;
|
||||
} else if _value < 1_00_000_000 {
|
||||
*self.by_size.entry(10_000_000).or_default() += &supply;
|
||||
} else if _value < 10_00_000_000 {
|
||||
*self.by_size.entry(1_00_000_000).or_default() += &supply;
|
||||
} else if _value < 100_00_000_000 {
|
||||
*self.by_size.entry(10_00_000_000).or_default() += &supply;
|
||||
} else if _value < 1_000_00_000_000 {
|
||||
*self.by_size.entry(100_00_000_000).or_default() += &supply;
|
||||
} else if _value < 10_000_00_000_000 {
|
||||
*self.by_size.entry(1_000_00_000_000).or_default() += &supply;
|
||||
} else if _value < 100_000_00_000_000 {
|
||||
*self.by_size.entry(10_000_00_000_000).or_default() += &supply;
|
||||
} else {
|
||||
*self.by_size.entry(100_000_00_000_000).or_default() += &supply;
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_by_size(
|
||||
first: BTreeMap<usize, SupplyState>,
|
||||
second: BTreeMap<usize, SupplyState>,
|
||||
) -> BTreeMap<usize, SupplyState> {
|
||||
let (mut source, to_consume) = if first.len() > second.len() {
|
||||
(first, second)
|
||||
} else {
|
||||
(second, first)
|
||||
};
|
||||
to_consume.into_iter().for_each(|(k, v)| {
|
||||
*source.entry(k).or_default() += &v;
|
||||
});
|
||||
source
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Transacted {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self {
|
||||
spendable_supply: self.spendable_supply + rhs.spendable_supply,
|
||||
by_type: self.by_type + rhs.by_type,
|
||||
by_size: Self::merge_by_size(self.by_size, rhs.by_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Transacted {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.by_size = Self::merge_by_size(mem::take(&mut self.by_size), rhs.by_size);
|
||||
self.spendable_supply += &rhs.spendable_supply;
|
||||
self.by_type += rhs.by_type;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
mod stores;
|
||||
mod vecs;
|
||||
|
||||
pub use stores::*;
|
||||
pub use vecs::*;
|
||||
@@ -1,222 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, TxIndex, WeekIndex,
|
||||
YearIndex,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, CollectableVec, Compressed, EagerVec, Result, StoredVec, Version,
|
||||
};
|
||||
|
||||
use crate::storage::{Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub txindex: Option<EagerVec<TxIndex, T>>,
|
||||
pub height: ComputedVecBuilder<Height, T>,
|
||||
pub dateindex: ComputedVecBuilder<DateIndex, T>,
|
||||
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
|
||||
pub yearindex: ComputedVecBuilder<YearIndex, T>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedType + Ord + From<f64>,
|
||||
f64: From<T>,
|
||||
{
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
name: &str,
|
||||
compute_source: bool,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let txindex = compute_source.then(|| {
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("txindex_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
let height = ComputedVecBuilder::forced_import(path, name, version, compressed, options)?;
|
||||
|
||||
let options = options.remove_percentiles();
|
||||
|
||||
Ok(Self {
|
||||
txindex,
|
||||
height,
|
||||
dateindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
difficultyepoch: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
monthindex: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
quarterindex: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
yearindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
// halvingepoch: StorableVecGeneator::forced_import(path, name, version, compressed, options)?,
|
||||
decadeindex: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut EagerVec<TxIndex, T>,
|
||||
&Indexer,
|
||||
&indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
{
|
||||
compute(
|
||||
self.txindex.as_mut().unwrap(),
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let txindex: Option<&StoredVec<TxIndex, T>> = None;
|
||||
self.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, T>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(txindex) = txindex {
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexes.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
} else {
|
||||
let txindex = self.txindex.as_ref().unwrap();
|
||||
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexes.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.dateindex.from_aligned(
|
||||
starting_indexes.dateindex,
|
||||
&self.height,
|
||||
&indexes.dateindex_to_first_height,
|
||||
&indexes.dateindex_to_height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.weekindex.from_aligned(
|
||||
starting_indexes.weekindex,
|
||||
&self.dateindex,
|
||||
&indexes.weekindex_to_first_dateindex,
|
||||
&indexes.weekindex_to_dateindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.monthindex.from_aligned(
|
||||
starting_indexes.monthindex,
|
||||
&self.dateindex,
|
||||
&indexes.monthindex_to_first_dateindex,
|
||||
&indexes.monthindex_to_dateindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.quarterindex.from_aligned(
|
||||
starting_indexes.quarterindex,
|
||||
&self.monthindex,
|
||||
&indexes.quarterindex_to_first_monthindex,
|
||||
&indexes.quarterindex_to_monthindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.yearindex.from_aligned(
|
||||
starting_indexes.yearindex,
|
||||
&self.monthindex,
|
||||
&indexes.yearindex_to_first_monthindex,
|
||||
&indexes.yearindex_to_monthindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.decadeindex.from_aligned(
|
||||
starting_indexes.decadeindex,
|
||||
&self.yearindex,
|
||||
&indexes.decadeindex_to_first_yearindex,
|
||||
&indexes.decadeindex_to_yearindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.difficultyepoch.from_aligned(
|
||||
starting_indexes.difficultyepoch,
|
||||
&self.height,
|
||||
&indexes.difficultyepoch_to_first_height,
|
||||
&indexes.difficultyepoch_to_height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.txindex
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
|
||||
self.height.vecs(),
|
||||
self.dateindex.vecs(),
|
||||
self.weekindex.vecs(),
|
||||
self.difficultyepoch.vecs(),
|
||||
self.monthindex.vecs(),
|
||||
self.quarterindex.vecs(),
|
||||
self.yearindex.vecs(),
|
||||
// self.halvingepoch.vecs(),
|
||||
self.decadeindex.vecs(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use std::ops::{Add, Div};
|
||||
|
||||
pub fn get_percentile<T>(sorted: &[T], percentile: f64) -> T
|
||||
where
|
||||
T: Clone + Div<usize, Output = T> + Add<T, Output = T>,
|
||||
{
|
||||
let len = sorted.len();
|
||||
|
||||
if len == 0 {
|
||||
panic!();
|
||||
} else if len == 1 {
|
||||
sorted[0].clone()
|
||||
} else {
|
||||
let index = (len - 1) as f64 * percentile;
|
||||
|
||||
let fract = index.fract();
|
||||
|
||||
if fract != 0.0 {
|
||||
let left = sorted.get(index as usize).unwrap().clone();
|
||||
let right = sorted.get(index.ceil() as usize).unwrap().clone();
|
||||
left / 2 + right / 2
|
||||
} else {
|
||||
// dbg!(sorted.len(), index);
|
||||
sorted.get(index as usize).unwrap().clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-12
@@ -11,7 +11,7 @@ use brk_vec::{AnyCollectableVec, AnyIterableVec, Compressed, Computation, EagerV
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromDateindex, ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ pub struct Vecs {
|
||||
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 timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
|
||||
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
|
||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||
pub indexes_to_block_size: ComputedVecsFromHeight<StoredUsize>,
|
||||
@@ -39,11 +39,12 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
height_to_interval: EagerVec::forced_import(
|
||||
&path.join("height_to_interval"),
|
||||
path,
|
||||
"interval",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
timeindexes_to_timestamp: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
@@ -85,11 +86,7 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
)?,
|
||||
height_to_vbytes: EagerVec::forced_import(
|
||||
&path.join("height_to_vbytes"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_vbytes: EagerVec::forced_import(path, "vbytes", Version::ZERO, compressed)?,
|
||||
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"block_vbytes",
|
||||
@@ -99,12 +96,14 @@ impl Vecs {
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
)?,
|
||||
difficultyepoch_to_timestamp: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_timestamp"),
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
halvingepoch_to_timestamp: EagerVec::forced_import(
|
||||
&path.join("halvingepoch_to_timestamp"),
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -242,6 +241,8 @@ impl Vecs {
|
||||
self.indexes_to_block_vbytes.vecs(),
|
||||
self.indexes_to_block_weight.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::StoredU8;
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, AnyVec, Compressed, Computation, Version};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub _0: ComputedVecsFromHeight<StoredU8>,
|
||||
pub _1: ComputedVecsFromHeight<StoredU8>,
|
||||
pub _50: ComputedVecsFromHeight<StoredU8>,
|
||||
pub _100: ComputedVecsFromHeight<StoredU8>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
_computation: Computation,
|
||||
compressed: Compressed,
|
||||
) -> color_eyre::Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
_0: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"0",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
_1: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"1",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
_50: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"50",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
_100: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"100",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self._0.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredU8::new(0)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self._1.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredU8::new(1)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self._50.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredU8::new(50)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self._100.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredU8::new(100)),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self._0.vecs(),
|
||||
self._1.vecs(),
|
||||
self._50.vecs(),
|
||||
self._100.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+67
-73
@@ -12,7 +12,7 @@ use brk_vec::{AnyCollectableVec, AnyIterableVec, Compressed, Computation, EagerV
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{
|
||||
ComputedVecsFromDateindex, ComputedVecsFromHeightStrict, StorableVecGeneatorOptions,
|
||||
ComputedVecsFromDateIndex, ComputedVecsFromHeightStrict, StorableVecGeneatorOptions,
|
||||
},
|
||||
indexes,
|
||||
};
|
||||
@@ -33,14 +33,14 @@ pub struct Vecs {
|
||||
pub height_to_ohlc_in_sats: EagerVec<Height, OHLCSats>,
|
||||
pub height_to_ohlc_in_cents: EagerVec<Height, OHLCCents>,
|
||||
pub height_to_open_in_cents: EagerVec<Height, Open<Cents>>,
|
||||
pub timeindexes_to_close: ComputedVecsFromDateindex<Close<Dollars>>,
|
||||
pub timeindexes_to_high: ComputedVecsFromDateindex<High<Dollars>>,
|
||||
pub timeindexes_to_low: ComputedVecsFromDateindex<Low<Dollars>>,
|
||||
pub timeindexes_to_open: ComputedVecsFromDateindex<Open<Dollars>>,
|
||||
pub timeindexes_to_open_in_sats: ComputedVecsFromDateindex<Open<Sats>>,
|
||||
pub timeindexes_to_high_in_sats: ComputedVecsFromDateindex<High<Sats>>,
|
||||
pub timeindexes_to_low_in_sats: ComputedVecsFromDateindex<Low<Sats>>,
|
||||
pub timeindexes_to_close_in_sats: ComputedVecsFromDateindex<Close<Sats>>,
|
||||
pub timeindexes_to_close: ComputedVecsFromDateIndex<Close<Dollars>>,
|
||||
pub timeindexes_to_high: ComputedVecsFromDateIndex<High<Dollars>>,
|
||||
pub timeindexes_to_low: ComputedVecsFromDateIndex<Low<Dollars>>,
|
||||
pub timeindexes_to_open: ComputedVecsFromDateIndex<Open<Dollars>>,
|
||||
pub timeindexes_to_open_in_sats: ComputedVecsFromDateIndex<Open<Sats>>,
|
||||
pub timeindexes_to_high_in_sats: ComputedVecsFromDateIndex<High<Sats>>,
|
||||
pub timeindexes_to_low_in_sats: ComputedVecsFromDateIndex<Low<Sats>>,
|
||||
pub timeindexes_to_close_in_sats: ComputedVecsFromDateIndex<Close<Sats>>,
|
||||
pub chainindexes_to_close: ComputedVecsFromHeightStrict<Close<Dollars>>,
|
||||
pub chainindexes_to_high: ComputedVecsFromHeightStrict<High<Dollars>>,
|
||||
pub chainindexes_to_low: ComputedVecsFromHeightStrict<Low<Dollars>>,
|
||||
@@ -82,125 +82,129 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
dateindex_to_ohlc_in_cents: EagerVec::forced_import(
|
||||
&fetched_path.join("dateindex_to_ohlc_in_cents"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_ohlc"),
|
||||
&fetched_path,
|
||||
"ohlc_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
dateindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_close_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_close_in_cents"),
|
||||
path,
|
||||
"close_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_high_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_high_in_cents"),
|
||||
path,
|
||||
"high_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_low_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_low_in_cents"),
|
||||
path,
|
||||
"low_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_open_in_cents: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_open_in_cents"),
|
||||
path,
|
||||
"open_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_ohlc_in_cents: EagerVec::forced_import(
|
||||
&fetched_path.join("height_to_ohlc_in_cents"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("height_to_ohlc"),
|
||||
&fetched_path,
|
||||
"ohlc_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
height_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("height_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_close_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_close_in_cents"),
|
||||
path,
|
||||
"close_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_high_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_high_in_cents"),
|
||||
path,
|
||||
"high_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_low_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_low_in_cents"),
|
||||
path,
|
||||
"low_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_open_in_cents: EagerVec::forced_import(
|
||||
&path.join("height_to_open_in_cents"),
|
||||
path,
|
||||
"open_in_cents",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
timeindexes_to_open: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_open: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"open",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_first(),
|
||||
)?,
|
||||
timeindexes_to_high: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_high: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"high",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_max(),
|
||||
)?,
|
||||
timeindexes_to_low: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_low: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"low",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_min(),
|
||||
)?,
|
||||
timeindexes_to_close: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_close: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"close",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
timeindexes_to_open_in_sats: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_open_in_sats: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"open_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_first(),
|
||||
)?,
|
||||
timeindexes_to_high_in_sats: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_high_in_sats: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"high_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_max(),
|
||||
)?,
|
||||
timeindexes_to_low_in_sats: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_low_in_sats: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"low_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_min(),
|
||||
)?,
|
||||
timeindexes_to_close_in_sats: ComputedVecsFromDateindex::forced_import(
|
||||
timeindexes_to_close_in_sats: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"close_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
@@ -263,64 +267,52 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
weekindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("weekindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
weekindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
weekindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("weekindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
difficultyepoch_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_ohlc"),
|
||||
path,
|
||||
"ohlc",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
difficultyepoch_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
monthindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("monthindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
monthindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
monthindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("monthindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
quarterindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
quarterindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
quarterindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
yearindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("yearindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
yearindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
yearindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("yearindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
// halvingepoch_to_ohlc: StorableVec::forced_import(&path.join("halvingepoch_to_ohlc"), Version::ZERO, compressed)?,
|
||||
decadeindex_to_ohlc: EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_ohlc"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
// halvingepoch_to_ohlc: StorableVec::forced_import(path,
|
||||
// "halvingepoch_to_ohlc"), Version::ZERO, compressed)?,
|
||||
decadeindex_to_ohlc: EagerVec::forced_import(path, "ohlc", Version::ZERO, compressed)?,
|
||||
decadeindex_to_ohlc_in_sats: EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_ohlc_in_sats"),
|
||||
path,
|
||||
"ohlc_in_sats",
|
||||
VERSION + VERSION_IN_SATS + Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -1097,6 +1089,8 @@ impl Vecs {
|
||||
self.chainindexes_to_low_in_sats.vecs(),
|
||||
self.chainindexes_to_open_in_sats.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+163
-120
@@ -8,6 +8,8 @@ use brk_vec::{
|
||||
};
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
|
||||
use crate::utils::get_percentile;
|
||||
|
||||
use super::ComputedType;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -16,18 +18,18 @@ where
|
||||
I: StoredIndex,
|
||||
T: ComputedType,
|
||||
{
|
||||
first: Option<EagerVec<I, T>>,
|
||||
average: Option<EagerVec<I, T>>,
|
||||
sum: Option<EagerVec<I, T>>,
|
||||
max: Option<EagerVec<I, T>>,
|
||||
_90p: Option<EagerVec<I, T>>,
|
||||
_75p: Option<EagerVec<I, T>>,
|
||||
median: Option<EagerVec<I, T>>,
|
||||
_25p: Option<EagerVec<I, T>>,
|
||||
_10p: Option<EagerVec<I, T>>,
|
||||
min: Option<EagerVec<I, T>>,
|
||||
last: Option<EagerVec<I, T>>,
|
||||
total: Option<EagerVec<I, T>>,
|
||||
pub first: Option<Box<EagerVec<I, T>>>,
|
||||
pub average: Option<Box<EagerVec<I, T>>>,
|
||||
pub sum: Option<Box<EagerVec<I, T>>>,
|
||||
pub max: Option<Box<EagerVec<I, T>>>,
|
||||
pub _90p: Option<Box<EagerVec<I, T>>>,
|
||||
pub _75p: Option<Box<EagerVec<I, T>>>,
|
||||
pub median: Option<Box<EagerVec<I, T>>>,
|
||||
pub _25p: Option<Box<EagerVec<I, T>>>,
|
||||
pub _10p: Option<Box<EagerVec<I, T>>>,
|
||||
pub min: Option<Box<EagerVec<I, T>>>,
|
||||
pub last: Option<Box<EagerVec<I, T>>>,
|
||||
pub total: Option<Box<EagerVec<I, T>>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -44,27 +46,23 @@ where
|
||||
compressed: Compressed,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let key = I::to_string().split("::").last().unwrap().to_lowercase();
|
||||
|
||||
let only_one_active = options.is_only_one_active();
|
||||
|
||||
let default = || path.join(format!("{key}_to_{name}"));
|
||||
|
||||
let prefix = |s: &str| path.join(format!("{key}_to_{s}_{name}"));
|
||||
let prefix = |s: &str| format!("{s}_{name}");
|
||||
|
||||
let maybe_prefix = |s: &str| {
|
||||
if only_one_active {
|
||||
default()
|
||||
name.to_string()
|
||||
} else {
|
||||
prefix(s)
|
||||
}
|
||||
};
|
||||
|
||||
let suffix = |s: &str| path.join(format!("{key}_to_{name}_{s}"));
|
||||
let suffix = |s: &str| format!("{name}_{s}");
|
||||
|
||||
let maybe_suffix = |s: &str| {
|
||||
if only_one_active {
|
||||
default()
|
||||
name.to_string()
|
||||
} else {
|
||||
suffix(s)
|
||||
}
|
||||
@@ -74,64 +72,131 @@ where
|
||||
|
||||
let s = Self {
|
||||
first: options.first.then(|| {
|
||||
EagerVec::forced_import(&maybe_prefix("first"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_prefix("first"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
last: options.last.then(|| {
|
||||
EagerVec::forced_import(
|
||||
&path.join(format!("{key}_to_{name}")),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
Box::new(
|
||||
EagerVec::forced_import(path, name, version + Version::ZERO, compressed)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
min: options.min.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("min"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("min"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
max: options.max.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("max"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("max"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
median: options.median.then(|| {
|
||||
EagerVec::forced_import(
|
||||
&maybe_suffix("median"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("median"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
average: options.average.then(|| {
|
||||
EagerVec::forced_import(
|
||||
&maybe_suffix("average"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("average"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
sum: options.sum.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("sum"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("sum"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
total: options.total.then(|| {
|
||||
EagerVec::forced_import(&prefix("total"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&prefix("total"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_90p: options._90p.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("90p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("90p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_75p: options._75p.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("75p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("75p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_25p: options._25p.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("25p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("25p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_10p: options._10p.then(|| {
|
||||
EagerVec::forced_import(&maybe_suffix("10p"), version + Version::ZERO, compressed)
|
||||
.unwrap()
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("10p"),
|
||||
version + Version::ZERO,
|
||||
compressed,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -176,12 +241,12 @@ where
|
||||
where
|
||||
I2: StoredIndex + StoredType + CheckedSub<I2>,
|
||||
{
|
||||
let index = self.starting_index(max_from);
|
||||
|
||||
self.validate_computed_version_or_reset_file(
|
||||
source.version() + first_indexes.version() + count_indexes.version(),
|
||||
)?;
|
||||
|
||||
let index = self.starting_index(max_from);
|
||||
|
||||
let mut count_indexes_iter = count_indexes.iter();
|
||||
let mut source_iter = source.iter();
|
||||
|
||||
@@ -269,23 +334,23 @@ where
|
||||
}
|
||||
|
||||
if let Some(_90p) = self._90p.as_mut() {
|
||||
_90p.forced_push_at(i, Self::get_percentile(&values, 0.90), exit)?;
|
||||
_90p.forced_push_at(i, get_percentile(&values, 0.90), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_75p) = self._75p.as_mut() {
|
||||
_75p.forced_push_at(i, Self::get_percentile(&values, 0.75), exit)?;
|
||||
_75p.forced_push_at(i, get_percentile(&values, 0.75), exit)?;
|
||||
}
|
||||
|
||||
if let Some(median) = self.median.as_mut() {
|
||||
median.forced_push_at(i, Self::get_percentile(&values, 0.50), exit)?;
|
||||
median.forced_push_at(i, get_percentile(&values, 0.50), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_25p) = self._25p.as_mut() {
|
||||
_25p.forced_push_at(i, Self::get_percentile(&values, 0.25), exit)?;
|
||||
_25p.forced_push_at(i, get_percentile(&values, 0.25), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_10p) = self._10p.as_mut() {
|
||||
_10p.forced_push_at(i, Self::get_percentile(&values, 0.10), exit)?;
|
||||
_10p.forced_push_at(i, get_percentile(&values, 0.10), exit)?;
|
||||
}
|
||||
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
@@ -472,116 +537,94 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_percentile(sorted: &[T], percentile: f64) -> T {
|
||||
let len = sorted.len();
|
||||
|
||||
if len == 0 {
|
||||
panic!();
|
||||
} else if len == 1 {
|
||||
sorted[0].clone()
|
||||
} else {
|
||||
let index = (len - 1) as f64 * percentile;
|
||||
|
||||
let fract = index.fract();
|
||||
|
||||
if fract != 0.0 {
|
||||
let left = sorted.get(index as usize).unwrap().clone();
|
||||
let right = sorted.get(index.ceil() as usize).unwrap().clone();
|
||||
left / 2 + right / 2
|
||||
} else {
|
||||
sorted.get(index as usize).unwrap().clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn starting_index(&self, max_from: I) -> I {
|
||||
pub fn starting_index(&self, max_from: I) -> I {
|
||||
max_from.min(I::from(
|
||||
self.vecs().into_iter().map(|v| v.len()).min().unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn unwrap_first(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.first.as_mut().unwrap()
|
||||
pub fn unwrap_first(&self) -> &EagerVec<I, T> {
|
||||
self.first.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_average(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.average.as_mut().unwrap()
|
||||
pub fn unwrap_average(&self) -> &EagerVec<I, T> {
|
||||
self.average.as_ref().unwrap()
|
||||
}
|
||||
pub fn unwrap_sum(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.sum.as_mut().unwrap()
|
||||
pub fn unwrap_sum(&self) -> &EagerVec<I, T> {
|
||||
self.sum.as_ref().unwrap()
|
||||
}
|
||||
pub fn unwrap_max(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.max.as_mut().unwrap()
|
||||
pub fn unwrap_max(&self) -> &EagerVec<I, T> {
|
||||
self.max.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_90p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._90p.as_mut().unwrap()
|
||||
pub fn unwrap_90p(&self) -> &EagerVec<I, T> {
|
||||
self._90p.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_75p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._75p.as_mut().unwrap()
|
||||
pub fn unwrap_75p(&self) -> &EagerVec<I, T> {
|
||||
self._75p.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_median(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.median.as_mut().unwrap()
|
||||
pub fn unwrap_median(&self) -> &EagerVec<I, T> {
|
||||
self.median.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_25p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._25p.as_mut().unwrap()
|
||||
pub fn unwrap_25p(&self) -> &EagerVec<I, T> {
|
||||
self._25p.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_10p(&mut self) -> &mut EagerVec<I, T> {
|
||||
self._10p.as_mut().unwrap()
|
||||
pub fn unwrap_10p(&self) -> &EagerVec<I, T> {
|
||||
self._10p.as_ref().unwrap()
|
||||
}
|
||||
pub fn unwrap_min(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.min.as_mut().unwrap()
|
||||
pub fn unwrap_min(&self) -> &EagerVec<I, T> {
|
||||
self.min.as_ref().unwrap()
|
||||
}
|
||||
pub fn unwrap_last(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.last.as_mut().unwrap()
|
||||
pub fn unwrap_last(&self) -> &EagerVec<I, T> {
|
||||
self.last.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_total(&mut self) -> &mut EagerVec<I, T> {
|
||||
self.total.as_mut().unwrap()
|
||||
pub fn unwrap_total(&self) -> &EagerVec<I, T> {
|
||||
self.total.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
let mut v: Vec<&dyn AnyCollectableVec> = vec![];
|
||||
|
||||
if let Some(first) = self.first.as_ref() {
|
||||
v.push(first);
|
||||
v.push(first.as_ref());
|
||||
}
|
||||
if let Some(last) = self.last.as_ref() {
|
||||
v.push(last);
|
||||
v.push(last.as_ref());
|
||||
}
|
||||
if let Some(min) = self.min.as_ref() {
|
||||
v.push(min);
|
||||
v.push(min.as_ref());
|
||||
}
|
||||
if let Some(max) = self.max.as_ref() {
|
||||
v.push(max);
|
||||
v.push(max.as_ref());
|
||||
}
|
||||
if let Some(median) = self.median.as_ref() {
|
||||
v.push(median);
|
||||
v.push(median.as_ref());
|
||||
}
|
||||
if let Some(average) = self.average.as_ref() {
|
||||
v.push(average);
|
||||
v.push(average.as_ref());
|
||||
}
|
||||
if let Some(sum) = self.sum.as_ref() {
|
||||
v.push(sum);
|
||||
v.push(sum.as_ref());
|
||||
}
|
||||
if let Some(total) = self.total.as_ref() {
|
||||
v.push(total);
|
||||
v.push(total.as_ref());
|
||||
}
|
||||
if let Some(_90p) = self._90p.as_ref() {
|
||||
v.push(_90p);
|
||||
v.push(_90p.as_ref());
|
||||
}
|
||||
if let Some(_75p) = self._75p.as_ref() {
|
||||
v.push(_75p);
|
||||
v.push(_75p.as_ref());
|
||||
}
|
||||
if let Some(_25p) = self._25p.as_ref() {
|
||||
v.push(_25p);
|
||||
v.push(_25p.as_ref());
|
||||
}
|
||||
if let Some(_10p) = self._10p.as_ref() {
|
||||
v.push(_10p);
|
||||
v.push(_10p.as_ref());
|
||||
}
|
||||
|
||||
v
|
||||
@@ -628,7 +671,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_computed_version_or_reset_file(&mut self, version: Version) -> Result<()> {
|
||||
pub fn validate_computed_version_or_reset_file(&mut self, version: Version) -> Result<()> {
|
||||
if let Some(first) = self.first.as_mut() {
|
||||
first.validate_computed_version_or_reset_file(Version::ZERO + version)?;
|
||||
}
|
||||
+16
-9
@@ -5,12 +5,12 @@ use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Compressed, EagerVec, Result, Version};
|
||||
|
||||
use crate::storage::{Indexes, indexes};
|
||||
use crate::vecs::{Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromDateindex<T>
|
||||
pub struct ComputedVecsFromDateIndex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
@@ -25,7 +25,7 @@ where
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedVecsFromDateindex<T>
|
||||
impl<T> ComputedVecsFromDateIndex<T>
|
||||
where
|
||||
T: ComputedType,
|
||||
{
|
||||
@@ -49,11 +49,7 @@ where
|
||||
let options = options.remove_percentiles();
|
||||
|
||||
Ok(Self {
|
||||
dateindex: EagerVec::forced_import(
|
||||
&path.join(format!("dateindex_to_{name}")),
|
||||
version,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex: EagerVec::forced_import(path, name, version, compressed)?,
|
||||
dateindex_extra,
|
||||
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
monthindex: ComputedVecBuilder::forced_import(
|
||||
@@ -94,6 +90,15 @@ where
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.compute_rest(indexes, starting_indexes, exit)
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.dateindex_extra
|
||||
.extend(starting_indexes.dateindex, &self.dateindex, exit)?;
|
||||
|
||||
@@ -150,6 +155,8 @@ where
|
||||
self.yearindex.vecs(),
|
||||
self.decadeindex.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+10
-12
@@ -7,7 +7,7 @@ use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, AnyIterableVec, Compressed, EagerVec, Result, Version};
|
||||
|
||||
use crate::storage::{Indexes, indexes};
|
||||
use crate::vecs::{Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
@@ -16,7 +16,7 @@ pub struct ComputedVecsFromHeight<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub height: Option<EagerVec<Height, T>>,
|
||||
pub height: Option<Box<EagerVec<Height, T>>>,
|
||||
pub height_extra: ComputedVecBuilder<Height, T>,
|
||||
pub dateindex: ComputedVecBuilder<DateIndex, T>,
|
||||
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
|
||||
@@ -45,10 +45,8 @@ where
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let height = compute_source.then(|| {
|
||||
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)
|
||||
.unwrap()
|
||||
});
|
||||
let height = compute_source
|
||||
.then(|| Box::new(EagerVec::forced_import(path, name, version, compressed).unwrap()));
|
||||
|
||||
let height_extra = ComputedVecBuilder::forced_import(
|
||||
path,
|
||||
@@ -105,9 +103,7 @@ where
|
||||
)?;
|
||||
|
||||
let height: Option<&EagerVec<Height, T>> = None;
|
||||
self.compute_rest(indexes, starting_indexes, exit, height)?;
|
||||
|
||||
Ok(())
|
||||
self.compute_rest(indexes, starting_indexes, exit, height)
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
@@ -137,7 +133,7 @@ where
|
||||
exit,
|
||||
)?;
|
||||
} else {
|
||||
let height = self.height.as_ref().unwrap();
|
||||
let height = self.height.as_ref().unwrap().as_ref();
|
||||
|
||||
self.height_extra
|
||||
.extend(starting_indexes.height, height, exit)?;
|
||||
@@ -206,7 +202,7 @@ where
|
||||
[
|
||||
self.height
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
|
||||
.map_or(vec![], |v| vec![v.as_ref() as &dyn AnyCollectableVec]),
|
||||
self.height_extra.vecs(),
|
||||
self.dateindex.vecs(),
|
||||
self.weekindex.vecs(),
|
||||
@@ -217,6 +213,8 @@ where
|
||||
// self.halvingepoch.vecs(),
|
||||
self.decadeindex.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -5,7 +5,7 @@ use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Compressed, EagerVec, Result, Version};
|
||||
|
||||
use crate::storage::{Indexes, indexes};
|
||||
use crate::vecs::{Indexes, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
@@ -36,8 +36,7 @@ where
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let height =
|
||||
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)?;
|
||||
let height = EagerVec::forced_import(path, name, version, compressed)?;
|
||||
|
||||
let height_extra = ComputedVecBuilder::forced_import(
|
||||
path,
|
||||
@@ -93,6 +92,8 @@ where
|
||||
self.difficultyepoch.vecs(),
|
||||
// self.halvingepoch.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,588 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_core::{
|
||||
Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, MonthIndex, QuarterIndex,
|
||||
Sats, TxIndex, WeekIndex, YearIndex,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyVec, CollectableVec, Compressed, EagerVec, Result, StoredIndex,
|
||||
VecIterator, Version,
|
||||
};
|
||||
|
||||
use crate::vecs::{Indexes, fetched, indexes};
|
||||
|
||||
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
{
|
||||
pub txindex: Option<Box<EagerVec<TxIndex, T>>>,
|
||||
pub height: ComputedVecBuilder<Height, T>,
|
||||
pub dateindex: ComputedVecBuilder<DateIndex, T>,
|
||||
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
|
||||
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
|
||||
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
|
||||
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
|
||||
pub yearindex: ComputedVecBuilder<YearIndex, T>,
|
||||
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
|
||||
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl<T> ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedType + Ord + From<f64>,
|
||||
f64: From<T>,
|
||||
{
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
name: &str,
|
||||
compute_source: bool,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let version = VERSION + version;
|
||||
|
||||
let txindex = compute_source
|
||||
.then(|| Box::new(EagerVec::forced_import(path, name, version, compressed).unwrap()));
|
||||
|
||||
let height = ComputedVecBuilder::forced_import(path, name, version, compressed, options)?;
|
||||
|
||||
let options = options.remove_percentiles();
|
||||
|
||||
Ok(Self {
|
||||
txindex,
|
||||
height,
|
||||
dateindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
difficultyepoch: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
monthindex: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
quarterindex: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
yearindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
|
||||
// halvingepoch: StorableVecGeneator::forced_import(path, name, version, compressed, options)?,
|
||||
decadeindex: ComputedVecBuilder::forced_import(
|
||||
path, name, version, compressed, options,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
// #[allow(unused)]
|
||||
// pub fn compute_all<F>(
|
||||
// &mut self,
|
||||
// indexer: &Indexer,
|
||||
// indexes: &indexes::Vecs,
|
||||
// starting_indexes: &Indexes,
|
||||
// exit: &Exit,
|
||||
// mut compute: F,
|
||||
// ) -> color_eyre::Result<()>
|
||||
// where
|
||||
// F: FnMut(
|
||||
// &mut EagerVec<TxIndex, T>,
|
||||
// &Indexer,
|
||||
// &indexes::Vecs,
|
||||
// &Indexes,
|
||||
// &Exit,
|
||||
// ) -> Result<()>,
|
||||
// {
|
||||
// compute(
|
||||
// self.txindex.as_mut().unwrap(),
|
||||
// indexer,
|
||||
// indexes,
|
||||
// starting_indexes,
|
||||
// exit,
|
||||
// )?;
|
||||
|
||||
// let txindex: Option<&StoredVec<TxIndex, T>> = None;
|
||||
// self.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, T>>,
|
||||
) -> Result<()> {
|
||||
if let Some(txindex) = txindex {
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexes.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
} else {
|
||||
let txindex = self.txindex.as_ref().unwrap().as_ref();
|
||||
|
||||
self.height.compute(
|
||||
starting_indexes.height,
|
||||
txindex,
|
||||
&indexer.vecs().height_to_first_txindex,
|
||||
&indexes.height_to_txindex_count,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.compute_after_height(indexes, starting_indexes, exit)
|
||||
}
|
||||
|
||||
fn compute_after_height(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.dateindex.from_aligned(
|
||||
starting_indexes.dateindex,
|
||||
&self.height,
|
||||
&indexes.dateindex_to_first_height,
|
||||
&indexes.dateindex_to_height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.weekindex.from_aligned(
|
||||
starting_indexes.weekindex,
|
||||
&self.dateindex,
|
||||
&indexes.weekindex_to_first_dateindex,
|
||||
&indexes.weekindex_to_dateindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.monthindex.from_aligned(
|
||||
starting_indexes.monthindex,
|
||||
&self.dateindex,
|
||||
&indexes.monthindex_to_first_dateindex,
|
||||
&indexes.monthindex_to_dateindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.quarterindex.from_aligned(
|
||||
starting_indexes.quarterindex,
|
||||
&self.monthindex,
|
||||
&indexes.quarterindex_to_first_monthindex,
|
||||
&indexes.quarterindex_to_monthindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.yearindex.from_aligned(
|
||||
starting_indexes.yearindex,
|
||||
&self.monthindex,
|
||||
&indexes.yearindex_to_first_monthindex,
|
||||
&indexes.yearindex_to_monthindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.decadeindex.from_aligned(
|
||||
starting_indexes.decadeindex,
|
||||
&self.yearindex,
|
||||
&indexes.decadeindex_to_first_yearindex,
|
||||
&indexes.decadeindex_to_yearindex_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.difficultyepoch.from_aligned(
|
||||
starting_indexes.difficultyepoch,
|
||||
&self.height,
|
||||
&indexes.difficultyepoch_to_first_height,
|
||||
&indexes.difficultyepoch_to_height_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.txindex
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v.as_ref() as &dyn AnyCollectableVec]),
|
||||
self.height.vecs(),
|
||||
self.dateindex.vecs(),
|
||||
self.weekindex.vecs(),
|
||||
self.difficultyepoch.vecs(),
|
||||
self.monthindex.vecs(),
|
||||
self.quarterindex.vecs(),
|
||||
self.yearindex.vecs(),
|
||||
// self.halvingepoch.vecs(),
|
||||
self.decadeindex.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
pub fn compute_rest_from_sats(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
sats: &ComputedVecsFromTxindex<Sats>,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, Bitcoin>>,
|
||||
) -> Result<()> {
|
||||
let txindex_version = if let Some(txindex) = txindex {
|
||||
txindex.version()
|
||||
} else {
|
||||
self.txindex.as_ref().unwrap().as_ref().version()
|
||||
};
|
||||
|
||||
self.height
|
||||
.validate_computed_version_or_reset_file(txindex_version)?;
|
||||
|
||||
let starting_index = self.height.starting_index(starting_indexes.height);
|
||||
|
||||
(starting_index.unwrap_to_usize()..indexer.vecs().height_to_weight.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|height| -> Result<()> {
|
||||
if let Some(first) = self.height.first.as_mut() {
|
||||
first.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_first()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(average) = self.height.average.as_mut() {
|
||||
average.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_average()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(sum) = self.height.sum.as_mut() {
|
||||
sum.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_sum()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(max) = self.height.max.as_mut() {
|
||||
max.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_max()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_90p) = self.height._90p.as_mut() {
|
||||
_90p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_90p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_75p) = self.height._75p.as_mut() {
|
||||
_75p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_75p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(median) = self.height.median.as_mut() {
|
||||
median.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_median()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_25p) = self.height._25p.as_mut() {
|
||||
_25p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_25p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_10p) = self.height._10p.as_mut() {
|
||||
_10p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_10p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(min) = self.height.min.as_mut() {
|
||||
min.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_min()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(last) = self.height.last.as_mut() {
|
||||
last.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_last()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(total) = self.height.total.as_mut() {
|
||||
total.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_total()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.height.safe_flush(exit)?;
|
||||
|
||||
self.compute_after_height(indexes, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedVecsFromTxindex<Dollars> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute_rest_from_bitcoin(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
bitcoin: &ComputedVecsFromTxindex<Bitcoin>,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, Dollars>>,
|
||||
fetched: &fetched::Vecs,
|
||||
) -> Result<()> {
|
||||
let txindex_version = if let Some(txindex) = txindex {
|
||||
txindex.version()
|
||||
} else {
|
||||
self.txindex.as_ref().unwrap().as_ref().version()
|
||||
};
|
||||
|
||||
self.height
|
||||
.validate_computed_version_or_reset_file(txindex_version)?;
|
||||
|
||||
let starting_index = self.height.starting_index(starting_indexes.height);
|
||||
|
||||
let mut close_iter = fetched.chainindexes_to_close.height.into_iter();
|
||||
|
||||
(starting_index.unwrap_to_usize()..indexer.vecs().height_to_weight.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|height| -> Result<()> {
|
||||
let price = *close_iter.unwrap_get_inner(height);
|
||||
|
||||
if let Some(first) = self.height.first.as_mut() {
|
||||
first.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_first()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(average) = self.height.average.as_mut() {
|
||||
average.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_average()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(sum) = self.height.sum.as_mut() {
|
||||
sum.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_sum()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(max) = self.height.max.as_mut() {
|
||||
max.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_max()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_90p) = self.height._90p.as_mut() {
|
||||
_90p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_90p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_75p) = self.height._75p.as_mut() {
|
||||
_75p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_75p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(median) = self.height.median.as_mut() {
|
||||
median.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_median()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_25p) = self.height._25p.as_mut() {
|
||||
_25p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_25p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_10p) = self.height._10p.as_mut() {
|
||||
_10p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_10p()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(min) = self.height.min.as_mut() {
|
||||
min.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_min()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(last) = self.height.last.as_mut() {
|
||||
last.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_last()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(total) = self.height.total.as_mut() {
|
||||
total.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_total()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.height.safe_flush(exit)?;
|
||||
|
||||
self.compute_after_height(indexes, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
+2
@@ -3,6 +3,7 @@ mod from_dateindex;
|
||||
mod from_height;
|
||||
mod from_height_strict;
|
||||
mod from_txindex;
|
||||
mod ratio_from_dateindex;
|
||||
mod r#type;
|
||||
mod value_from_height;
|
||||
mod value_from_txindex;
|
||||
@@ -12,6 +13,7 @@ pub use from_dateindex::*;
|
||||
pub use from_height::*;
|
||||
pub use from_height_strict::*;
|
||||
pub use from_txindex::*;
|
||||
pub use ratio_from_dateindex::*;
|
||||
use r#type::*;
|
||||
pub use value_from_height::*;
|
||||
pub use value_from_txindex::*;
|
||||
@@ -0,0 +1,935 @@
|
||||
use std::{f32, path::Path};
|
||||
|
||||
use brk_core::{Date, DateIndex, Dollars, StoredF32};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyIterableVec, AnyVec, CollectableVec, Compressed, EagerVec, Result,
|
||||
StoredIndex, VecIterator, Version,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
utils::get_percentile,
|
||||
vecs::{Indexes, fetched, indexes},
|
||||
};
|
||||
|
||||
use super::{ComputedVecsFromDateIndex, StorableVecGeneatorOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ComputedRatioVecsFromDateIndex {
|
||||
pub price: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
|
||||
pub ratio: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1w_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_standard_deviation: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_9: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_5: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p1: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p0_5: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p0_1: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p1sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p2sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p3sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_m1sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_m2sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_m3sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_9_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p99_5_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p99_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p1_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p0_5_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p0_1_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_p3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_m1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_m2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_m3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl ComputedRatioVecsFromDateIndex {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
name: &str,
|
||||
compute_source: bool,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
Ok(Self {
|
||||
price: compute_source.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
name,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
options,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
ratio: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_sma"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_1w_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1w_sma"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_1m_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1m_sma"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_1y_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1y_sma"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1y_sma_momentum_oscillator"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_standard_deviation: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_standard_deviation"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p99_9: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p99_9"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p99_5: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p99_5"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p99: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p99"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p1: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p1"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p0_5: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p0_5"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p0_1: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p0_1"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p1sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p1sd"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p2sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p2sd"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p3sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p3sd"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_m1sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_m1sd"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_m2sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_m2sd"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_m3sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_m3sd"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p99_9_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p99_9_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p99_5_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p99_5_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p99_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p99_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p1_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p1_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p0_5_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p0_5_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p0_1_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p0_1_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p1sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p1sd_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p2sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p2sd_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_p3sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_p3sd_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_m1sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_m1sd_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_m2sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_m2sd_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_m3sd_as_price: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_m3sd_as_price"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
ratio_zscore: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_zscore"),
|
||||
VERSION + version + Version::ZERO,
|
||||
compressed,
|
||||
options,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
fetched: &fetched::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
compute: F,
|
||||
) -> color_eyre::Result<()>
|
||||
where
|
||||
F: FnMut(
|
||||
&mut EagerVec<DateIndex, Dollars>,
|
||||
&Indexer,
|
||||
&indexes::Vecs,
|
||||
&Indexes,
|
||||
&Exit,
|
||||
) -> Result<()>,
|
||||
{
|
||||
self.price
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute(indexer, indexes, starting_indexes, exit, compute)?;
|
||||
|
||||
let date_to_price_opt: Option<&EagerVec<DateIndex, Dollars>> = None;
|
||||
self.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
date_to_price_opt,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
fetched: &fetched::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
date_to_price_opt: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
) -> color_eyre::Result<()> {
|
||||
let date_to_price = date_to_price_opt.unwrap_or_else(|| unsafe {
|
||||
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
||||
});
|
||||
|
||||
let closes = &fetched.timeindexes_to_close.dateindex;
|
||||
|
||||
self.ratio.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
let mut price = date_to_price.iter();
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
closes,
|
||||
|(i, close, ..)| {
|
||||
let price = price.unwrap_get_inner(i);
|
||||
if price == Dollars::ZERO {
|
||||
(i, StoredF32::from(1.0))
|
||||
} else {
|
||||
(i, StoredF32::from(*close / price))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let min_ratio_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
||||
|
||||
self.ratio_sma.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
usize::MAX,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1w_sma.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
7,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1m_sma.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
30,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1y_sma.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma_(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
365,
|
||||
exit,
|
||||
Some(min_ratio_date),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1y_sma_momentum_oscillator.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
let mut ratio_1y_sma_iter = self.ratio_1y_sma.dateindex.into_iter();
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
|(i, ratio, ..)| {
|
||||
(
|
||||
i,
|
||||
StoredF32::from(*ratio / *ratio_1y_sma_iter.unwrap_get_inner(i) - 1.0),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let ratio_version = self.ratio.dateindex.version();
|
||||
self.mut_ratio_vecs()
|
||||
.iter_mut()
|
||||
.try_for_each(|v| -> Result<()> {
|
||||
v.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + v.inner_version() + ratio_version,
|
||||
)
|
||||
})?;
|
||||
|
||||
let starting_dateindex = self
|
||||
.mut_ratio_vecs()
|
||||
.iter()
|
||||
.map(|v| DateIndex::from(v.len()))
|
||||
.min()
|
||||
.unwrap()
|
||||
.min(starting_indexes.dateindex);
|
||||
|
||||
let mut sorted = self.ratio.dateindex.collect_range(
|
||||
Some(min_ratio_date.unwrap_to_usize()),
|
||||
Some(starting_dateindex.unwrap_to_usize()),
|
||||
)?;
|
||||
|
||||
sorted.sort_unstable();
|
||||
|
||||
// if sorted.len() != starting_dateindex.unwrap_to_usize() - min_ratio_date.unwrap_to_usize() {
|
||||
// unreachable!();
|
||||
// }
|
||||
|
||||
let mut sma_iter = self.ratio_sma.dateindex.into_iter();
|
||||
|
||||
let nan = StoredF32::from(f32::NAN);
|
||||
self.ratio
|
||||
.dateindex
|
||||
.iter_at(starting_dateindex)
|
||||
.try_for_each(|(index, ratio)| -> Result<()> {
|
||||
if index < min_ratio_date {
|
||||
self.ratio_p0_1.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p0_5.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p1.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p99.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p99_5
|
||||
.dateindex
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p99_9
|
||||
.dateindex
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_standard_deviation
|
||||
.dateindex
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
|
||||
self.ratio_p1sd.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p2sd.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_p3sd.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_m1sd.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_m2sd.dateindex.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_m3sd.dateindex.forced_push_at(index, nan, exit)?;
|
||||
} else {
|
||||
let ratio = ratio.into_inner();
|
||||
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
|
||||
sorted.insert(pos, ratio);
|
||||
self.ratio_p0_1.dateindex.forced_push_at(
|
||||
index,
|
||||
get_percentile(&sorted, 0.001),
|
||||
exit,
|
||||
)?;
|
||||
self.ratio_p0_5.dateindex.forced_push_at(
|
||||
index,
|
||||
get_percentile(&sorted, 0.005),
|
||||
exit,
|
||||
)?;
|
||||
self.ratio_p1.dateindex.forced_push_at(
|
||||
index,
|
||||
get_percentile(&sorted, 0.01),
|
||||
exit,
|
||||
)?;
|
||||
self.ratio_p99.dateindex.forced_push_at(
|
||||
index,
|
||||
get_percentile(&sorted, 0.99),
|
||||
exit,
|
||||
)?;
|
||||
self.ratio_p99_5.dateindex.forced_push_at(
|
||||
index,
|
||||
get_percentile(&sorted, 0.995),
|
||||
exit,
|
||||
)?;
|
||||
self.ratio_p99_9.dateindex.forced_push_at(
|
||||
index,
|
||||
get_percentile(&sorted, 0.999),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let avg = sma_iter.unwrap_get_inner(index);
|
||||
|
||||
let sd = StoredF32::from(
|
||||
(sorted.iter().map(|v| (**v - *avg).powi(2)).sum::<f32>()
|
||||
/ (index.unwrap_to_usize() + 1) as f32)
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.ratio_standard_deviation
|
||||
.dateindex
|
||||
.forced_push_at(index, sd, exit)?;
|
||||
|
||||
self.ratio_p1sd
|
||||
.dateindex
|
||||
.forced_push_at(index, avg + sd, exit)?;
|
||||
self.ratio_p2sd
|
||||
.dateindex
|
||||
.forced_push_at(index, avg + 2 * sd, exit)?;
|
||||
self.ratio_p3sd
|
||||
.dateindex
|
||||
.forced_push_at(index, avg + 3 * sd, exit)?;
|
||||
self.ratio_m1sd
|
||||
.dateindex
|
||||
.forced_push_at(index, avg - sd, exit)?;
|
||||
self.ratio_m2sd
|
||||
.dateindex
|
||||
.forced_push_at(index, avg - 2 * sd, exit)?;
|
||||
self.ratio_m3sd
|
||||
.dateindex
|
||||
.forced_push_at(index, avg - 3 * sd, exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.mut_ratio_vecs()
|
||||
.into_iter()
|
||||
.try_for_each(|v| v.safe_flush(exit))?;
|
||||
|
||||
self.ratio_p99_9
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p99_5
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p99
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p1
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p0_5
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p0_1
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_standard_deviation
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p1sd
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p2sd
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_p3sd
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_m1sd
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_m2sd
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
self.ratio_m3sd
|
||||
.compute_rest(indexes, starting_indexes, exit)?;
|
||||
|
||||
let date_to_price = date_to_price_opt.unwrap_or_else(|| unsafe {
|
||||
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
|
||||
});
|
||||
|
||||
self.ratio_p99_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p99.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p99_5_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p99_5.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p99_9_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p99_9.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p1_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p1.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p0_5_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p0_5.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p0_1_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p0_1.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p1sd_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p1sd.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p2sd_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p2sd.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_p3sd_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_p3sd.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_m1sd_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_m1sd.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_m2sd_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_m2sd.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_m3sd_as_price.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut iter = self.ratio_m3sd.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.unwrap_get_inner(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_zscore.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut sma_iter = self.ratio_sma.dateindex.into_iter();
|
||||
let mut sd_iter = self.ratio_standard_deviation.dateindex.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&self.ratio.dateindex,
|
||||
|(i, ratio, ..)| {
|
||||
let sma = sma_iter.unwrap_get_inner(i);
|
||||
let sd = sd_iter.unwrap_get_inner(i);
|
||||
(i, (ratio - sma) / sd)
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
|
||||
vec![
|
||||
&mut self.ratio_standard_deviation.dateindex,
|
||||
&mut self.ratio_p99_9.dateindex,
|
||||
&mut self.ratio_p99_5.dateindex,
|
||||
&mut self.ratio_p99.dateindex,
|
||||
&mut self.ratio_p1.dateindex,
|
||||
&mut self.ratio_p0_5.dateindex,
|
||||
&mut self.ratio_p0_1.dateindex,
|
||||
&mut self.ratio_p1sd.dateindex,
|
||||
&mut self.ratio_p2sd.dateindex,
|
||||
&mut self.ratio_p3sd.dateindex,
|
||||
&mut self.ratio_m1sd.dateindex,
|
||||
&mut self.ratio_m2sd.dateindex,
|
||||
&mut self.ratio_m3sd.dateindex,
|
||||
]
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.price.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
self.ratio.vecs(),
|
||||
self.ratio_sma.vecs(),
|
||||
self.ratio_1w_sma.vecs(),
|
||||
self.ratio_1m_sma.vecs(),
|
||||
self.ratio_1y_sma.vecs(),
|
||||
self.ratio_1y_sma_momentum_oscillator.vecs(),
|
||||
self.ratio_standard_deviation.vecs(),
|
||||
self.ratio_p99_9.vecs(),
|
||||
self.ratio_p99_5.vecs(),
|
||||
self.ratio_p99.vecs(),
|
||||
self.ratio_p1.vecs(),
|
||||
self.ratio_p0_5.vecs(),
|
||||
self.ratio_p0_1.vecs(),
|
||||
self.ratio_p1sd.vecs(),
|
||||
self.ratio_p2sd.vecs(),
|
||||
self.ratio_p3sd.vecs(),
|
||||
self.ratio_m1sd.vecs(),
|
||||
self.ratio_m2sd.vecs(),
|
||||
self.ratio_m3sd.vecs(),
|
||||
self.ratio_p99_9_as_price.vecs(),
|
||||
self.ratio_p99_5_as_price.vecs(),
|
||||
self.ratio_p99_as_price.vecs(),
|
||||
self.ratio_p1_as_price.vecs(),
|
||||
self.ratio_p0_5_as_price.vecs(),
|
||||
self.ratio_p0_1_as_price.vecs(),
|
||||
self.ratio_p1sd_as_price.vecs(),
|
||||
self.ratio_p2sd_as_price.vecs(),
|
||||
self.ratio_p3sd_as_price.vecs(),
|
||||
self.ratio_m1sd_as_price.vecs(),
|
||||
self.ratio_m2sd_as_price.vecs(),
|
||||
self.ratio_m3sd_as_price.vecs(),
|
||||
self.ratio_zscore.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+16
-19
@@ -7,10 +7,7 @@ use brk_vec::{
|
||||
AnyCollectableVec, CollectableVec, Compressed, EagerVec, Result, StoredVec, Version,
|
||||
};
|
||||
|
||||
use crate::storage::{
|
||||
marketprice,
|
||||
vecs::{Indexes, indexes},
|
||||
};
|
||||
use crate::vecs::{Indexes, fetched, indexes};
|
||||
|
||||
use super::{ComputedVecsFromHeight, StorableVecGeneatorOptions};
|
||||
|
||||
@@ -68,7 +65,7 @@ impl ComputedValueVecsFromHeight {
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
@@ -91,14 +88,7 @@ impl ComputedValueVecsFromHeight {
|
||||
)?;
|
||||
|
||||
let height: Option<&StoredVec<Height, Sats>> = None;
|
||||
self.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
marketprices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
height,
|
||||
)?;
|
||||
self.compute_rest(indexer, indexes, fetched, starting_indexes, exit, height)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -107,7 +97,7 @@ impl ComputedValueVecsFromHeight {
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
height: Option<&impl CollectableVec<Height, Sats>>,
|
||||
@@ -139,15 +129,15 @@ impl ComputedValueVecsFromHeight {
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_from_sats(
|
||||
starting_indexes.height,
|
||||
self.sats.height.as_ref().unwrap(),
|
||||
self.sats.height.as_ref().unwrap().as_ref(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
let txindex = self.bitcoin.height.as_ref().unwrap();
|
||||
let price = &marketprices.as_ref().unwrap().chainindexes_to_close.height;
|
||||
let height_to_bitcoin = self.bitcoin.height.as_ref().unwrap().as_ref();
|
||||
let height_to_close = &fetched.as_ref().unwrap().chainindexes_to_close.height;
|
||||
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.compute_all(
|
||||
@@ -156,7 +146,12 @@ impl ComputedValueVecsFromHeight {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_from_bitcoin(starting_indexes.height, txindex, price, exit)
|
||||
v.compute_from_bitcoin(
|
||||
starting_indexes.height,
|
||||
height_to_bitcoin,
|
||||
height_to_close,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
}
|
||||
@@ -170,6 +165,8 @@ impl ComputedValueVecsFromHeight {
|
||||
self.bitcoin.vecs(),
|
||||
self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+23
-17
@@ -8,10 +8,7 @@ use brk_vec::{
|
||||
Computation, ComputedVecFrom3, LazyVecFrom1, StoredIndex, StoredVec, Version,
|
||||
};
|
||||
|
||||
use crate::storage::{
|
||||
marketprice,
|
||||
vecs::{Indexes, indexes},
|
||||
};
|
||||
use crate::vecs::{Indexes, fetched, indexes};
|
||||
|
||||
use super::{ComputedVecsFromTxindex, StorableVecGeneatorOptions};
|
||||
|
||||
@@ -48,11 +45,14 @@ impl ComputedValueVecsFromTxindex {
|
||||
version: Version,
|
||||
computation: Computation,
|
||||
compressed: Compressed,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_source = source.is_none();
|
||||
let compute_dollars = marketprices.is_some();
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
let name_in_btc = format!("{name}_in_btc");
|
||||
let name_in_usd = format!("{name}_in_usd");
|
||||
|
||||
let sats = ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
@@ -64,7 +64,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
)?;
|
||||
|
||||
let bitcoin_txindex = LazyVecFrom1::init(
|
||||
"txindex_to_{name}_in_btc",
|
||||
&name_in_btc,
|
||||
VERSION + version,
|
||||
source.map_or_else(|| sats.txindex.as_ref().unwrap().boxed_clone(), |s| s),
|
||||
|txindex: TxIndex, iter| {
|
||||
@@ -77,23 +77,23 @@ impl ComputedValueVecsFromTxindex {
|
||||
|
||||
let bitcoin = ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
&format!("{name}_in_btc"),
|
||||
&name_in_btc,
|
||||
false,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
options,
|
||||
)?;
|
||||
|
||||
let dollars_txindex = marketprices.map(|marketprices| {
|
||||
let dollars_txindex = fetched.map(|fetched| {
|
||||
ComputedVecFrom3::forced_import_or_init_from_3(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_{name}_in_usd",
|
||||
&name_in_usd,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
bitcoin_txindex.boxed_clone(),
|
||||
indexes.txindex_to_height.boxed_clone(),
|
||||
marketprices.chainindexes_to_close.height.boxed_clone(),
|
||||
fetched.chainindexes_to_close.height.boxed_clone(),
|
||||
|txindex: TxIndex,
|
||||
txindex_to_btc_iter,
|
||||
txindex_to_height_iter,
|
||||
@@ -123,7 +123,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
dollars: compute_dollars.then(|| {
|
||||
ComputedVecsFromTxindex::forced_import(
|
||||
path,
|
||||
&format!("{name}_in_usd"),
|
||||
&name_in_usd,
|
||||
false,
|
||||
VERSION + version,
|
||||
compressed,
|
||||
@@ -138,7 +138,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
// &mut self,
|
||||
// indexer: &Indexer,
|
||||
// indexes: &indexes::Vecs,
|
||||
// marketprices: Option<&marketprice::Vecs>,
|
||||
// fetched: Option<&marketprice::Vecs>,
|
||||
// starting_indexes: &Indexes,
|
||||
// exit: &Exit,
|
||||
// mut compute: F,
|
||||
@@ -164,7 +164,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
// self.compute_rest(
|
||||
// indexer,
|
||||
// indexes,
|
||||
// marketprices,
|
||||
// fetched,
|
||||
// starting_indexes,
|
||||
// exit,
|
||||
// txindex,
|
||||
@@ -180,6 +180,7 @@ impl ComputedValueVecsFromTxindex {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
txindex: Option<&impl CollectableVec<TxIndex, Sats>>,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(txindex) = txindex {
|
||||
self.sats
|
||||
@@ -190,11 +191,12 @@ impl ComputedValueVecsFromTxindex {
|
||||
.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?;
|
||||
}
|
||||
|
||||
self.bitcoin.compute_rest(
|
||||
self.bitcoin.compute_rest_from_sats(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&self.sats,
|
||||
Some(&self.bitcoin_txindex),
|
||||
)?;
|
||||
|
||||
@@ -203,12 +205,14 @@ impl ComputedValueVecsFromTxindex {
|
||||
|
||||
dollars_txindex.compute_if_necessary(starting_indexes.txindex, exit)?;
|
||||
|
||||
dollars.compute_rest(
|
||||
dollars.compute_rest_from_bitcoin(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&self.bitcoin,
|
||||
Some(dollars_txindex),
|
||||
fetched.as_ref().unwrap(),
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -221,6 +225,8 @@ impl ComputedValueVecsFromTxindex {
|
||||
self.bitcoin.vecs(),
|
||||
self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+144
-99
@@ -11,7 +11,7 @@ use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, CloneableAnyIterableVec, Compressed, Computation, ComputedVec,
|
||||
ComputedVecFrom1, EagerVec, VecIterator, Version,
|
||||
ComputedVecFrom1, ComputedVecFrom2, EagerVec, StoredIndex, VecIterator, Version,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -53,6 +53,7 @@ pub struct Vecs {
|
||||
pub opreturnindex_to_opreturnindex:
|
||||
ComputedVecFrom1<OpReturnIndex, OpReturnIndex, OpReturnIndex, TxIndex>,
|
||||
pub outputindex_to_outputindex: ComputedVecFrom1<OutputIndex, OutputIndex, OutputIndex, Sats>,
|
||||
pub outputindex_to_txindex: EagerVec<OutputIndex, TxIndex>,
|
||||
pub p2aindex_to_p2aindex: ComputedVecFrom1<P2AIndex, P2AIndex, P2AIndex, P2ABytes>,
|
||||
pub p2msindex_to_p2msindex: ComputedVecFrom1<P2MSIndex, P2MSIndex, P2MSIndex, TxIndex>,
|
||||
pub p2pk33index_to_p2pk33index:
|
||||
@@ -70,6 +71,10 @@ pub struct Vecs {
|
||||
pub quarterindex_to_quarterindex:
|
||||
ComputedVecFrom1<QuarterIndex, QuarterIndex, QuarterIndex, MonthIndex>,
|
||||
pub txindex_to_height: EagerVec<TxIndex, Height>,
|
||||
pub txindex_to_input_count:
|
||||
ComputedVecFrom2<TxIndex, StoredUsize, TxIndex, InputIndex, InputIndex, OutputIndex>,
|
||||
pub txindex_to_output_count:
|
||||
ComputedVecFrom2<TxIndex, StoredUsize, TxIndex, OutputIndex, OutputIndex, Sats>,
|
||||
pub txindex_to_txindex: ComputedVecFrom1<TxIndex, TxIndex, TxIndex, Txid>,
|
||||
pub unknownoutputindex_to_unknownoutputindex:
|
||||
ComputedVecFrom1<UnknownOutputIndex, UnknownOutputIndex, UnknownOutputIndex, TxIndex>,
|
||||
@@ -94,7 +99,7 @@ impl Vecs {
|
||||
let outputindex_to_outputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"outputindex_to_outputindex",
|
||||
"outputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
@@ -104,7 +109,7 @@ impl Vecs {
|
||||
let inputindex_to_inputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"inputindex_to_inputindex",
|
||||
"inputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
@@ -114,17 +119,63 @@ impl Vecs {
|
||||
let txindex_to_txindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_txindex",
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_txid.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let txindex_to_input_count = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"input_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_first_inputindex_iter, inputindex_to_outputindex_iter| {
|
||||
let txindex = index.unwrap_to_usize();
|
||||
txindex_to_first_inputindex_iter
|
||||
.next_at(txindex)
|
||||
.map(|(_, start)| {
|
||||
let start = usize::from(start.into_inner());
|
||||
let end = txindex_to_first_inputindex_iter
|
||||
.next_at(txindex + 1)
|
||||
.map(|(_, v)| usize::from(v.into_inner()))
|
||||
.unwrap_or_else(|| inputindex_to_outputindex_iter.len());
|
||||
StoredUsize::from((start..end).count())
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let txindex_to_output_count = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"output_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_first_outputindex_iter, outputindex_to_value_iter| {
|
||||
let txindex = index.unwrap_to_usize();
|
||||
txindex_to_first_outputindex_iter
|
||||
.next_at(txindex)
|
||||
.map(|(_, start)| {
|
||||
let start = usize::from(start.into_inner());
|
||||
let end = txindex_to_first_outputindex_iter
|
||||
.next_at(txindex + 1)
|
||||
.map(|(_, v)| usize::from(v.into_inner()))
|
||||
.unwrap_or_else(|| outputindex_to_value_iter.len());
|
||||
StoredUsize::from((start..end).count())
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let p2pk33index_to_p2pk33index = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pk33index_to_p2pk33index",
|
||||
"p2pk33index",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2pk33index_to_p2pk33bytes.boxed_clone(),
|
||||
@@ -133,7 +184,7 @@ impl Vecs {
|
||||
let p2pk65index_to_p2pk65index = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pk65index_to_p2pk65index",
|
||||
"p2pk65index",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2pk65index_to_p2pk65bytes.boxed_clone(),
|
||||
@@ -142,7 +193,7 @@ impl Vecs {
|
||||
let p2pkhindex_to_p2pkhindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2pkhindex_to_p2pkhindex",
|
||||
"p2pkhindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2pkhindex_to_p2pkhbytes.boxed_clone(),
|
||||
@@ -151,7 +202,7 @@ impl Vecs {
|
||||
let p2shindex_to_p2shindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2shindex_to_p2shindex",
|
||||
"p2shindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2shindex_to_p2shbytes.boxed_clone(),
|
||||
@@ -160,7 +211,7 @@ impl Vecs {
|
||||
let p2trindex_to_p2trindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2trindex_to_p2trindex",
|
||||
"p2trindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2trindex_to_p2trbytes.boxed_clone(),
|
||||
@@ -169,7 +220,7 @@ impl Vecs {
|
||||
let p2wpkhindex_to_p2wpkhindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2wpkhindex_to_p2wpkhindex",
|
||||
"p2wpkhindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2wpkhindex_to_p2wpkhbytes.boxed_clone(),
|
||||
@@ -178,7 +229,7 @@ impl Vecs {
|
||||
let p2wshindex_to_p2wshindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2wshindex_to_p2wshindex",
|
||||
"p2wshindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2wshindex_to_p2wshbytes.boxed_clone(),
|
||||
@@ -187,7 +238,7 @@ impl Vecs {
|
||||
let p2aindex_to_p2aindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2aindex_to_p2aindex",
|
||||
"p2aindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2aindex_to_p2abytes.boxed_clone(),
|
||||
@@ -196,7 +247,7 @@ impl Vecs {
|
||||
let p2msindex_to_p2msindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"p2msindex_to_p2msindex",
|
||||
"p2msindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().p2msindex_to_txindex.boxed_clone(),
|
||||
@@ -205,7 +256,7 @@ impl Vecs {
|
||||
let emptyoutputindex_to_emptyoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"emptyoutputindex_to_emptyoutputindex",
|
||||
"emptyoutputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().emptyoutputindex_to_txindex.boxed_clone(),
|
||||
@@ -214,7 +265,7 @@ impl Vecs {
|
||||
let unknownoutputindex_to_unknownoutputindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"unknownoutputindex_to_unknownoutputindex",
|
||||
"unknownoutputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().unknownoutputindex_to_txindex.boxed_clone(),
|
||||
@@ -223,23 +274,20 @@ impl Vecs {
|
||||
let opreturnindex_to_opreturnindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"opreturnindex_to_opreturnindex",
|
||||
"opreturnindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().opreturnindex_to_txindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let dateindex_to_first_height = EagerVec::forced_import(
|
||||
&path.join("dateindex_to_first_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let dateindex_to_first_height =
|
||||
EagerVec::forced_import(path, "first_height", Version::ZERO, compressed)?;
|
||||
|
||||
let dateindex_to_dateindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"dateindex_to_dateindex",
|
||||
"dateindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
dateindex_to_first_height.boxed_clone(),
|
||||
@@ -249,20 +297,19 @@ impl Vecs {
|
||||
let dateindex_to_date = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"dateindex_to_date",
|
||||
"date",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
dateindex_to_dateindex.boxed_clone(),
|
||||
|index, _| Some(Date::from(index)),
|
||||
)?;
|
||||
|
||||
let height_to_date =
|
||||
EagerVec::forced_import(&path.join("height_to_date"), Version::ZERO, compressed)?;
|
||||
let height_to_date = EagerVec::forced_import(path, "date", Version::ZERO, compressed)?;
|
||||
|
||||
let height_to_height = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"height_to_height",
|
||||
"height",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
height_to_date.boxed_clone(),
|
||||
@@ -272,23 +319,20 @@ impl Vecs {
|
||||
let height_to_difficultyepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"height_to_difficultyepoch",
|
||||
"difficultyepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
height_to_height.boxed_clone(),
|
||||
|index, _| Some(DifficultyEpoch::from(index)),
|
||||
)?;
|
||||
|
||||
let difficultyepoch_to_first_height = EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_first_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let difficultyepoch_to_first_height =
|
||||
EagerVec::forced_import(path, "first_height", Version::ZERO, compressed)?;
|
||||
|
||||
let difficultyepoch_to_difficultyepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"difficultyepoch_to_difficultyepoch",
|
||||
"difficultyepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
difficultyepoch_to_first_height.boxed_clone(),
|
||||
@@ -298,67 +342,52 @@ impl Vecs {
|
||||
let height_to_halvingepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"height_to_halvingepoch",
|
||||
"halvingepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
height_to_height.boxed_clone(),
|
||||
|index, _| Some(HalvingEpoch::from(index)),
|
||||
)?;
|
||||
|
||||
let halvingepoch_to_first_height = EagerVec::forced_import(
|
||||
&path.join("halvingepoch_to_first_height"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let halvingepoch_to_first_height =
|
||||
EagerVec::forced_import(path, "first_height", Version::ZERO, compressed)?;
|
||||
|
||||
let halvingepoch_to_halvingepoch = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"halvingepoch_to_halvingepoch",
|
||||
"halvingepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
halvingepoch_to_first_height.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let dateindex_to_weekindex = EagerVec::forced_import(
|
||||
&path.join("dateindex_to_weekindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let dateindex_to_weekindex =
|
||||
EagerVec::forced_import(path, "weekindex", Version::ZERO, compressed)?;
|
||||
|
||||
let weekindex_to_first_dateindex = EagerVec::forced_import(
|
||||
&path.join("weekindex_to_first_dateindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let weekindex_to_first_dateindex =
|
||||
EagerVec::forced_import(path, "first_dateindex", Version::ZERO, compressed)?;
|
||||
|
||||
let weekindex_to_weekindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"weekindex_to_weekindex",
|
||||
"weekindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
weekindex_to_first_dateindex.boxed_clone(),
|
||||
|index, _| Some(index),
|
||||
)?;
|
||||
|
||||
let dateindex_to_monthindex = EagerVec::forced_import(
|
||||
&path.join("dateindex_to_monthindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let dateindex_to_monthindex =
|
||||
EagerVec::forced_import(path, "monthindex", Version::ZERO, compressed)?;
|
||||
|
||||
let monthindex_to_first_dateindex = EagerVec::forced_import(
|
||||
&path.join("monthindex_to_first_dateindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let monthindex_to_first_dateindex =
|
||||
EagerVec::forced_import(path, "first_dateindex", Version::ZERO, compressed)?;
|
||||
|
||||
let monthindex_to_monthindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"monthindex_to_monthindex",
|
||||
"monthindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
monthindex_to_first_dateindex.boxed_clone(),
|
||||
@@ -368,23 +397,20 @@ impl Vecs {
|
||||
let monthindex_to_quarterindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"monthindex_to_quarterindex",
|
||||
"quarterindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
monthindex_to_monthindex.boxed_clone(),
|
||||
|index, _| Some(QuarterIndex::from(index)),
|
||||
)?;
|
||||
|
||||
let quarterindex_to_first_monthindex = EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_first_monthindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let quarterindex_to_first_monthindex =
|
||||
EagerVec::forced_import(path, "first_monthindex", Version::ZERO, compressed)?;
|
||||
|
||||
let quarterindex_to_quarterindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"quarterindex_to_quarterindex",
|
||||
"quarterindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
quarterindex_to_first_monthindex.boxed_clone(),
|
||||
@@ -394,23 +420,20 @@ impl Vecs {
|
||||
let monthindex_to_yearindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"monthindex_to_yearindex",
|
||||
"yearindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
monthindex_to_monthindex.boxed_clone(),
|
||||
|index, _| Some(YearIndex::from(index)),
|
||||
)?;
|
||||
|
||||
let yearindex_to_first_monthindex = EagerVec::forced_import(
|
||||
&path.join("yearindex_to_first_monthindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let yearindex_to_first_monthindex =
|
||||
EagerVec::forced_import(path, "first_monthindex", Version::ZERO, compressed)?;
|
||||
|
||||
let yearindex_to_yearindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"yearindex_to_yearindex",
|
||||
"yearindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
yearindex_to_first_monthindex.boxed_clone(),
|
||||
@@ -420,23 +443,20 @@ impl Vecs {
|
||||
let yearindex_to_decadeindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"yearindex_to_decadeindex",
|
||||
"decadeindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
yearindex_to_yearindex.boxed_clone(),
|
||||
|index, _| Some(DecadeIndex::from(index)),
|
||||
)?;
|
||||
|
||||
let decadeindex_to_first_yearindex = EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_first_yearindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?;
|
||||
let decadeindex_to_first_yearindex =
|
||||
EagerVec::forced_import(path, "first_yearindex", Version::ZERO, compressed)?;
|
||||
|
||||
let decadeindex_to_decadeindex = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"decadeindex_to_decadeindex",
|
||||
"decadeindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
decadeindex_to_first_yearindex.boxed_clone(),
|
||||
@@ -479,6 +499,8 @@ impl Vecs {
|
||||
quarterindex_to_first_monthindex,
|
||||
quarterindex_to_quarterindex,
|
||||
txindex_to_txindex,
|
||||
txindex_to_input_count,
|
||||
txindex_to_output_count,
|
||||
unknownoutputindex_to_unknownoutputindex,
|
||||
weekindex_to_first_dateindex,
|
||||
weekindex_to_weekindex,
|
||||
@@ -486,62 +508,75 @@ impl Vecs {
|
||||
yearindex_to_first_monthindex,
|
||||
yearindex_to_yearindex,
|
||||
height_to_date_fixed: EagerVec::forced_import(
|
||||
&path.join("height_to_date_fixed"),
|
||||
path,
|
||||
"date_fixed",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_dateindex: EagerVec::forced_import(
|
||||
&path.join("height_to_dateindex"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_height: EagerVec::forced_import(
|
||||
&path.join("txindex_to_height"),
|
||||
path,
|
||||
"dateindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_height: EagerVec::forced_import(path, "height", Version::ZERO, compressed)?,
|
||||
height_to_timestamp_fixed: EagerVec::forced_import(
|
||||
&path.join("height_to_timestamp_fixed"),
|
||||
path,
|
||||
"timestamp_fixed",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_txindex_count: EagerVec::forced_import(
|
||||
&path.join("height_to_txindex_count"),
|
||||
path,
|
||||
"txindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
dateindex_to_height_count: EagerVec::forced_import(
|
||||
&path.join("dateindex_to_height_count"),
|
||||
path,
|
||||
"height_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
weekindex_to_dateindex_count: EagerVec::forced_import(
|
||||
&path.join("weekindex_to_dateindex_count"),
|
||||
path,
|
||||
"dateindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
difficultyepoch_to_height_count: EagerVec::forced_import(
|
||||
&path.join("difficultyepoch_to_height_count"),
|
||||
path,
|
||||
"height_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
monthindex_to_dateindex_count: EagerVec::forced_import(
|
||||
&path.join("monthindex_to_dateindex_count"),
|
||||
path,
|
||||
"dateindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
quarterindex_to_monthindex_count: EagerVec::forced_import(
|
||||
&path.join("quarterindex_to_monthindex_count"),
|
||||
path,
|
||||
"monthindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
yearindex_to_monthindex_count: EagerVec::forced_import(
|
||||
&path.join("yearindex_to_monthindex_count"),
|
||||
path,
|
||||
"monthindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
decadeindex_to_yearindex_count: EagerVec::forced_import(
|
||||
&path.join("decadeindex_to_yearindex_count"),
|
||||
path,
|
||||
"yearindex_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
outputindex_to_txindex: EagerVec::forced_import(
|
||||
path,
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
@@ -563,6 +598,13 @@ impl Vecs {
|
||||
self.outputindex_to_outputindex
|
||||
.compute_if_necessary(starting_indexes.outputindex, exit)?;
|
||||
|
||||
self.outputindex_to_txindex.compute_inverse_less_to_more(
|
||||
starting_indexes.txindex,
|
||||
&indexer_vecs.txindex_to_first_outputindex,
|
||||
&self.txindex_to_output_count,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.p2pk33index_to_p2pk33index
|
||||
.compute_if_necessary(starting_indexes.p2pk33index, exit)?;
|
||||
|
||||
@@ -993,6 +1035,8 @@ impl Vecs {
|
||||
&self.quarterindex_to_quarterindex,
|
||||
&self.txindex_to_height,
|
||||
&self.txindex_to_txindex,
|
||||
&self.txindex_to_input_count,
|
||||
&self.txindex_to_output_count,
|
||||
&self.unknownoutputindex_to_unknownoutputindex,
|
||||
&self.weekindex_to_dateindex_count,
|
||||
&self.weekindex_to_first_dateindex,
|
||||
@@ -1001,6 +1045,7 @@ impl Vecs {
|
||||
&self.yearindex_to_first_monthindex,
|
||||
&self.yearindex_to_monthindex_count,
|
||||
&self.yearindex_to_yearindex,
|
||||
&self.outputindex_to_txindex,
|
||||
]
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+8
-6
@@ -7,15 +7,15 @@ use brk_vec::{AnyCollectableVec, Compressed, Computation, VecIterator, Version};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromDateindex, ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateindex<DifficultyEpoch>,
|
||||
pub indexes_to_halvingepoch: ComputedVecsFromDateindex<HalvingEpoch>,
|
||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
|
||||
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -35,14 +35,14 @@ impl Vecs {
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_difficultyepoch: ComputedVecsFromDateindex::forced_import(
|
||||
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"difficultyepoch",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_halvingepoch: ComputedVecsFromDateindex::forced_import(
|
||||
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"halvingepoch",
|
||||
Version::ZERO,
|
||||
@@ -123,6 +123,8 @@ impl Vecs {
|
||||
self.indexes_to_difficultyepoch.vecs(),
|
||||
self.indexes_to_halvingepoch.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -6,21 +6,27 @@ use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Compressed, Computation};
|
||||
|
||||
pub mod blocks;
|
||||
pub mod constants;
|
||||
pub mod fetched;
|
||||
pub mod grouped;
|
||||
pub mod indexes;
|
||||
pub mod marketprice;
|
||||
pub mod market;
|
||||
pub mod mining;
|
||||
pub mod transactions;
|
||||
pub mod utxos;
|
||||
|
||||
pub use indexes::Indexes;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub indexes: indexes::Vecs,
|
||||
pub constants: constants::Vecs,
|
||||
pub blocks: blocks::Vecs,
|
||||
pub mining: mining::Vecs,
|
||||
pub market: market::Vecs,
|
||||
pub transactions: transactions::Vecs,
|
||||
pub marketprice: Option<marketprice::Vecs>,
|
||||
pub utxos: utxos::Vecs,
|
||||
pub fetched: Option<fetched::Vecs>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -35,22 +41,25 @@ impl Vecs {
|
||||
|
||||
let indexes = indexes::Vecs::forced_import(path, indexer, computation, compressed)?;
|
||||
|
||||
let marketprice =
|
||||
fetch.then(|| marketprice::Vecs::forced_import(path, computation, compressed).unwrap());
|
||||
let fetched =
|
||||
fetch.then(|| fetched::Vecs::forced_import(path, computation, compressed).unwrap());
|
||||
|
||||
Ok(Self {
|
||||
blocks: blocks::Vecs::forced_import(path, computation, compressed)?,
|
||||
mining: mining::Vecs::forced_import(path, computation, compressed)?,
|
||||
constants: constants::Vecs::forced_import(path, computation, compressed)?,
|
||||
market: market::Vecs::forced_import(path, computation, compressed)?,
|
||||
utxos: utxos::Vecs::forced_import(path, computation, compressed, fetched.as_ref())?,
|
||||
transactions: transactions::Vecs::forced_import(
|
||||
path,
|
||||
indexer,
|
||||
&indexes,
|
||||
computation,
|
||||
compressed,
|
||||
marketprice.as_ref(),
|
||||
fetched.as_ref(),
|
||||
)?,
|
||||
indexes,
|
||||
marketprice,
|
||||
fetched,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -63,14 +72,17 @@ impl Vecs {
|
||||
) -> color_eyre::Result<()> {
|
||||
let starting_indexes = self.indexes.compute(indexer, starting_indexes, exit)?;
|
||||
|
||||
self.constants
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
self.blocks
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
self.mining
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
if let Some(marketprice) = self.marketprice.as_mut() {
|
||||
marketprice.compute(
|
||||
if let Some(fetched) = self.fetched.as_mut() {
|
||||
fetched.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
@@ -83,7 +95,27 @@ impl Vecs {
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
self.marketprice.as_ref(),
|
||||
self.fetched.as_ref(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
if let Some(fetched) = self.fetched.as_ref() {
|
||||
self.market.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
fetched,
|
||||
&mut self.transactions,
|
||||
&starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.utxos.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&self.transactions,
|
||||
self.fetched.as_ref(),
|
||||
&starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -92,12 +124,17 @@ impl Vecs {
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.constants.vecs(),
|
||||
self.indexes.vecs(),
|
||||
self.blocks.vecs(),
|
||||
self.mining.vecs(),
|
||||
self.market.vecs(),
|
||||
self.transactions.vecs(),
|
||||
self.marketprice.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
self.utxos.vecs(),
|
||||
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
+136
-82
@@ -1,24 +1,25 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{
|
||||
CheckedSub, Feerate, Height, InputIndex, OutputIndex, Sats, StoredU32, StoredUsize, TxIndex,
|
||||
TxVersion, Weight,
|
||||
CheckedSub, Feerate, HalvingEpoch, Height, InputIndex, OutputIndex, Sats, StoredU32,
|
||||
StoredUsize, TxIndex, TxVersion, Weight,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_parser::bitcoin;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyIterableVec, CloneableAnyIterableVec, Compressed, Computation,
|
||||
ComputedVec, ComputedVecFrom1, ComputedVecFrom2, ComputedVecFrom3, StoredIndex, Version,
|
||||
ComputedVec, ComputedVecFrom1, ComputedVecFrom2, ComputedVecFrom3, StoredIndex, VecIterator,
|
||||
Version,
|
||||
};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
Indexes, fetched,
|
||||
grouped::{
|
||||
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight,
|
||||
ComputedVecsFromTxindex, StorableVecGeneatorOptions,
|
||||
},
|
||||
indexes, marketprice,
|
||||
indexes,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -64,6 +65,7 @@ pub struct Vecs {
|
||||
pub indexes_to_p2wpkh_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_p2wsh_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_unclaimed_rewards: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_tx_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_tx_v1: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub indexes_to_tx_v2: ComputedVecsFromHeight<StoredUsize>,
|
||||
@@ -73,18 +75,15 @@ pub struct Vecs {
|
||||
pub indexes_to_unknownoutput_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
pub inputindex_to_value:
|
||||
ComputedVecFrom2<InputIndex, Sats, InputIndex, OutputIndex, OutputIndex, Sats>,
|
||||
pub txindex_to_input_count:
|
||||
ComputedVecFrom2<TxIndex, StoredUsize, TxIndex, InputIndex, InputIndex, OutputIndex>,
|
||||
pub indexes_to_input_count: ComputedVecsFromTxindex<StoredUsize>,
|
||||
pub txindex_to_is_coinbase: ComputedVecFrom2<TxIndex, bool, TxIndex, Height, Height, TxIndex>,
|
||||
pub txindex_to_output_count:
|
||||
ComputedVecFrom2<TxIndex, StoredUsize, TxIndex, OutputIndex, OutputIndex, Sats>,
|
||||
pub indexes_to_output_count: ComputedVecsFromTxindex<StoredUsize>,
|
||||
pub txindex_to_vsize: ComputedVecFrom1<TxIndex, StoredUsize, TxIndex, Weight>,
|
||||
pub txindex_to_weight:
|
||||
ComputedVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
|
||||
pub txindex_to_fee: ComputedVecFrom2<TxIndex, Sats, TxIndex, Sats, TxIndex, Sats>,
|
||||
pub txindex_to_feerate: ComputedVecFrom2<TxIndex, Feerate, TxIndex, Sats, TxIndex, StoredUsize>,
|
||||
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -94,16 +93,16 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
computation: Computation,
|
||||
compressed: Compressed,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_dollars = marketprices.is_some();
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
let inputindex_to_value = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"inputindex_to_value",
|
||||
"value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
@@ -130,7 +129,7 @@ impl Vecs {
|
||||
let txindex_to_weight = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_weight",
|
||||
"weight",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_base_size.boxed_clone(),
|
||||
@@ -158,7 +157,7 @@ impl Vecs {
|
||||
let txindex_to_vsize = ComputedVec::forced_import_or_init_from_1(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_vsize",
|
||||
"vsize",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
txindex_to_weight.boxed_clone(),
|
||||
@@ -175,7 +174,7 @@ impl Vecs {
|
||||
let txindex_to_is_coinbase = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_is_coinbase",
|
||||
"is_coinbase",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexes.txindex_to_height.boxed_clone(),
|
||||
@@ -196,37 +195,14 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
let txindex_to_input_count = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_input_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
indexer.vecs().inputindex_to_outputindex.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_first_inputindex_iter, inputindex_to_outputindex_iter| {
|
||||
let txindex = index.unwrap_to_usize();
|
||||
txindex_to_first_inputindex_iter
|
||||
.next_at(txindex)
|
||||
.map(|(_, start)| {
|
||||
let start = usize::from(start.into_inner());
|
||||
let end = txindex_to_first_inputindex_iter
|
||||
.next_at(txindex + 1)
|
||||
.map(|(_, v)| usize::from(v.into_inner()))
|
||||
.unwrap_or_else(|| inputindex_to_outputindex_iter.len());
|
||||
StoredUsize::from((start..end).count())
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let txindex_to_input_value = ComputedVec::forced_import_or_init_from_3(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_input_value",
|
||||
"input_value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_inputindex.boxed_clone(),
|
||||
txindex_to_input_count.boxed_clone(),
|
||||
indexes.txindex_to_input_count.boxed_clone(),
|
||||
inputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex,
|
||||
txindex_to_first_inputindex_iter,
|
||||
@@ -268,37 +244,14 @@ impl Vecs {
|
||||
// .add_total(),
|
||||
// )?;
|
||||
|
||||
let txindex_to_output_count = ComputedVec::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_output_count",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex, txindex_to_first_outputindex_iter, outputindex_to_value_iter| {
|
||||
let txindex = index.unwrap_to_usize();
|
||||
txindex_to_first_outputindex_iter
|
||||
.next_at(txindex)
|
||||
.map(|(_, start)| {
|
||||
let start = usize::from(start.into_inner());
|
||||
let end = txindex_to_first_outputindex_iter
|
||||
.next_at(txindex + 1)
|
||||
.map(|(_, v)| usize::from(v.into_inner()))
|
||||
.unwrap_or_else(|| outputindex_to_value_iter.len());
|
||||
StoredUsize::from((start..end).count())
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let txindex_to_output_value = ComputedVec::forced_import_or_init_from_3(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_output_value",
|
||||
"output_value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
indexer.vecs().txindex_to_first_outputindex.boxed_clone(),
|
||||
txindex_to_output_count.boxed_clone(),
|
||||
indexes.txindex_to_output_count.boxed_clone(),
|
||||
indexer.vecs().outputindex_to_value.boxed_clone(),
|
||||
|index: TxIndex,
|
||||
txindex_to_first_outputindex_iter,
|
||||
@@ -343,7 +296,7 @@ impl Vecs {
|
||||
let txindex_to_fee = ComputedVecFrom2::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_fee",
|
||||
"fee",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
txindex_to_input_value.boxed_clone(),
|
||||
@@ -366,7 +319,7 @@ impl Vecs {
|
||||
let txindex_to_feerate = ComputedVecFrom2::forced_import_or_init_from_2(
|
||||
computation,
|
||||
path,
|
||||
"txindex_to_feerate",
|
||||
"feerate",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
txindex_to_fee.boxed_clone(),
|
||||
@@ -455,7 +408,7 @@ impl Vecs {
|
||||
Version::ZERO,
|
||||
computation,
|
||||
compressed,
|
||||
marketprices,
|
||||
fetched,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_total()
|
||||
@@ -524,6 +477,15 @@ impl Vecs {
|
||||
.add_average(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_unclaimed_rewards: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"unclaimed_rewards",
|
||||
true,
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_sum().add_total(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_p2a_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"p2a_count",
|
||||
@@ -680,6 +642,14 @@ impl Vecs {
|
||||
.add_sum()
|
||||
.add_total(),
|
||||
)?,
|
||||
indexes_to_exact_utxo_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"exact_utxo_count",
|
||||
true,
|
||||
Version::TWO,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
txindex_to_is_coinbase,
|
||||
inputindex_to_value,
|
||||
// indexes_to_input_value,
|
||||
@@ -690,8 +660,6 @@ impl Vecs {
|
||||
txindex_to_feerate,
|
||||
txindex_to_vsize,
|
||||
txindex_to_weight,
|
||||
txindex_to_input_count,
|
||||
txindex_to_output_count,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -700,7 +668,7 @@ impl Vecs {
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
marketprices: Option<&marketprice::Vecs>,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.indexes_to_tx_count.compute_all(
|
||||
@@ -723,7 +691,7 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.txindex_to_input_count),
|
||||
Some(&indexes.txindex_to_input_count),
|
||||
)?;
|
||||
|
||||
self.indexes_to_output_count.compute_rest(
|
||||
@@ -731,7 +699,7 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.txindex_to_output_count),
|
||||
Some(&indexes.txindex_to_output_count),
|
||||
)?;
|
||||
|
||||
let compute_indexes_to_tx_vany =
|
||||
@@ -816,6 +784,7 @@ impl Vecs {
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.txindex_to_fee),
|
||||
fetched,
|
||||
)?;
|
||||
|
||||
self.indexes_to_feerate.compute_rest(
|
||||
@@ -845,13 +814,13 @@ impl Vecs {
|
||||
self.indexes_to_coinbase.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
marketprices,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, indexer, _, starting_indexes, exit| {
|
||||
let mut txindex_to_first_outputindex_iter =
|
||||
indexer.vecs().txindex_to_first_outputindex.iter();
|
||||
let mut txindex_to_output_count_iter = self.txindex_to_output_count.iter();
|
||||
let mut txindex_to_output_count_iter = indexes.txindex_to_output_count.iter();
|
||||
let mut outputindex_to_value_iter = indexer.vecs().outputindex_to_value.iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
@@ -878,7 +847,7 @@ impl Vecs {
|
||||
self.indexes_to_subsidy.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
marketprices,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
@@ -886,10 +855,41 @@ impl Vecs {
|
||||
self.indexes_to_fee.sats.height.unwrap_sum().iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_coinbase.sats.height.as_ref().unwrap(),
|
||||
|(height, subsidy, ..)| {
|
||||
self.indexes_to_coinbase
|
||||
.sats
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref(),
|
||||
|(height, coinbase, ..)| {
|
||||
let fees = indexes_to_fee_sum_iter.unwrap_get_inner(height);
|
||||
(height, subsidy.checked_sub(fees).unwrap())
|
||||
(height, coinbase.checked_sub(fees).unwrap())
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_unclaimed_rewards.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_subsidy
|
||||
.sats
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.as_ref(),
|
||||
|(height, subsidy, ..)| {
|
||||
let halving = HalvingEpoch::from(height);
|
||||
let expected =
|
||||
Sats::FIFTY_BTC / 2_usize.pow(halving.unwrap_to_usize() as u32);
|
||||
(height, expected.checked_sub(subsidy).unwrap())
|
||||
},
|
||||
exit,
|
||||
)
|
||||
@@ -1076,6 +1076,58 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_exact_utxo_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
let mut input_count_iter = self
|
||||
.indexes_to_input_count
|
||||
.height
|
||||
.unwrap_total()
|
||||
.into_iter();
|
||||
let mut opreturn_count_iter = self
|
||||
.indexes_to_opreturn_count
|
||||
.height_extra
|
||||
.unwrap_total()
|
||||
.into_iter();
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_output_count.height.unwrap_total(),
|
||||
|(h, output_count, ..)| {
|
||||
let input_count = input_count_iter.unwrap_get_inner(h);
|
||||
let opreturn_count = opreturn_count_iter.unwrap_get_inner(h);
|
||||
let block_count = usize::from(h + 1_usize);
|
||||
// -1 > genesis output is unspendable
|
||||
let mut utxo_count =
|
||||
*output_count - (*input_count - block_count) - *opreturn_count - 1;
|
||||
|
||||
// txid dup: e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468
|
||||
// Block 91_722 https://mempool.space/block/00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e
|
||||
// Block 91_880 https://mempool.space/block/00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721
|
||||
//
|
||||
// txid dup: d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599
|
||||
// Block 91_812 https://mempool.space/block/00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f
|
||||
// Block 91_842 https://mempool.space/block/00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec
|
||||
//
|
||||
// Warning: Dups invalidate the previous coinbase according to
|
||||
// https://chainquery.com/bitcoin-cli/gettxoutsetinfo
|
||||
|
||||
if h >= Height::new(91_842) {
|
||||
utxo_count -= 1;
|
||||
}
|
||||
if h >= Height::new(91_880) {
|
||||
utxo_count -= 1;
|
||||
}
|
||||
|
||||
(h, StoredUsize::from(utxo_count))
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1085,10 +1137,8 @@ impl Vecs {
|
||||
&self.inputindex_to_value as &dyn AnyCollectableVec,
|
||||
&self.txindex_to_fee,
|
||||
&self.txindex_to_feerate,
|
||||
&self.txindex_to_input_count,
|
||||
&self.txindex_to_input_value,
|
||||
&self.txindex_to_is_coinbase,
|
||||
&self.txindex_to_output_count,
|
||||
&self.txindex_to_output_value,
|
||||
&self.txindex_to_vsize,
|
||||
&self.txindex_to_weight,
|
||||
@@ -1117,7 +1167,11 @@ impl Vecs {
|
||||
self.indexes_to_tx_vsize.vecs(),
|
||||
self.indexes_to_tx_weight.vecs(),
|
||||
self.indexes_to_unknownoutput_count.vecs(),
|
||||
self.indexes_to_exact_utxo_count.vecs(),
|
||||
self.indexes_to_unclaimed_rewards.vecs(),
|
||||
]
|
||||
.concat()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{CheckedSub, Dollars, Height, Sats, StoredUsize};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyVec, Compressed, Computation, EagerVec, Result, VecIterator, Version,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
states::{CohortState, RealizedState},
|
||||
vecs::{
|
||||
Indexes, fetched,
|
||||
grouped::{
|
||||
ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight, ComputedVecsFromHeight,
|
||||
StorableVecGeneatorOptions,
|
||||
},
|
||||
indexes,
|
||||
},
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
pub struct Vecs {
|
||||
starting_height: Height,
|
||||
pub state: CohortState,
|
||||
|
||||
pub height_to_realized_cap: Option<EagerVec<Height, Dollars>>,
|
||||
pub indexes_to_realized_cap: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
pub height_to_supply: EagerVec<Height, Sats>,
|
||||
pub indexes_to_supply: ComputedValueVecsFromHeight,
|
||||
pub height_to_utxo_count: EagerVec<Height, StoredUsize>,
|
||||
pub indexes_to_utxo_count: ComputedVecsFromHeight<StoredUsize>,
|
||||
|
||||
pub indexes_to_realized_price: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
pub indexes_to_realized_price_extra: Option<ComputedRatioVecsFromDateIndex>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
cohort_name: Option<&str>,
|
||||
_computation: Computation,
|
||||
compressed: Compressed,
|
||||
version: Version,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
// let prefix = |s: &str| cohort_name.map_or(s.to_string(), |name| format!("{s}_{name}"));
|
||||
|
||||
let suffix = |s: &str| cohort_name.map_or(s.to_string(), |name| format!("{name}_{s}"));
|
||||
|
||||
let mut state = CohortState::default();
|
||||
if compute_dollars {
|
||||
state.realized = Some(RealizedState::NAN);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
starting_height: Height::ZERO,
|
||||
state,
|
||||
|
||||
height_to_realized_cap: compute_dollars.then(|| {
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&suffix("realized_cap"),
|
||||
VERSION + Version::ZERO + version,
|
||||
compressed,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("realized_cap"),
|
||||
false,
|
||||
VERSION + Version::ZERO + version,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_supply: EagerVec::forced_import(
|
||||
path,
|
||||
&suffix("supply"),
|
||||
VERSION + Version::ZERO + version,
|
||||
compressed,
|
||||
)?,
|
||||
indexes_to_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("supply"),
|
||||
false,
|
||||
VERSION + Version::ZERO + version,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
height_to_utxo_count: EagerVec::forced_import(
|
||||
path,
|
||||
&suffix("utxo_count"),
|
||||
VERSION + Version::ZERO + version,
|
||||
compressed,
|
||||
)?,
|
||||
indexes_to_utxo_count: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("utxo_count"),
|
||||
false,
|
||||
VERSION + Version::ZERO + version,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
indexes_to_realized_price: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("realized_price"),
|
||||
true,
|
||||
VERSION + Version::new(2) + version,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_realized_price_extra: compute_dollars.then(|| {
|
||||
ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&suffix("realized_price"),
|
||||
false,
|
||||
VERSION + Version::new(2) + version,
|
||||
compressed,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn starting_height(&self) -> Height {
|
||||
[
|
||||
self.height_to_supply.len(),
|
||||
self.height_to_utxo_count.len(),
|
||||
self.height_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(usize::MAX, |v| v.len()),
|
||||
]
|
||||
.into_iter()
|
||||
.map(Height::from)
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn init(&mut self, starting_height: Height) {
|
||||
if starting_height > self.starting_height() {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
self.starting_height = starting_height;
|
||||
|
||||
if let Some(prev_height) = starting_height.checked_sub(Height::new(1)) {
|
||||
self.state.supply.value = self
|
||||
.height_to_supply
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height);
|
||||
self.state.supply.utxos = *self
|
||||
.height_to_utxo_count
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height);
|
||||
|
||||
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
||||
self.state.realized.as_mut().unwrap().realized_cap = height_to_realized_cap
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||
self.height_to_supply
|
||||
.validate_computed_version_or_reset_file(
|
||||
base_version + self.height_to_supply.inner_version(),
|
||||
)?;
|
||||
|
||||
self.height_to_utxo_count
|
||||
.validate_computed_version_or_reset_file(
|
||||
base_version + self.height_to_utxo_count.inner_version(),
|
||||
)?;
|
||||
|
||||
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut().as_mut() {
|
||||
height_to_realized_cap.validate_computed_version_or_reset_file(
|
||||
base_version + height_to_realized_cap.inner_version(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn forced_pushed_at(&mut self, height: Height, exit: &Exit) -> Result<()> {
|
||||
if self.starting_height > height {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.height_to_supply
|
||||
.forced_push_at(height, self.state.supply.value, exit)?;
|
||||
|
||||
self.height_to_utxo_count.forced_push_at(
|
||||
height,
|
||||
StoredUsize::from(self.state.supply.utxos),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
||||
height_to_realized_cap.forced_push_at(
|
||||
height,
|
||||
self.state
|
||||
.realized
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| {
|
||||
dbg!(&self.state);
|
||||
panic!();
|
||||
})
|
||||
.realized_cap,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn safe_flush_height_vecs(&mut self, exit: &Exit) -> Result<()> {
|
||||
self.height_to_supply.safe_flush(exit)?;
|
||||
|
||||
self.height_to_utxo_count.safe_flush(exit)?;
|
||||
|
||||
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
|
||||
height_to_realized_cap.safe_flush(exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
self.indexes_to_supply.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_supply),
|
||||
)?;
|
||||
|
||||
self.indexes_to_utxo_count.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_utxo_count),
|
||||
)?;
|
||||
|
||||
if let Some(indexes_to_realized_cap) = self.indexes_to_realized_cap.as_mut() {
|
||||
indexes_to_realized_cap.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.height_to_realized_cap.as_ref().unwrap()),
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(indexes_to_realized_price) = self.indexes_to_realized_price.as_mut() {
|
||||
indexes_to_realized_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
self.height_to_realized_cap.as_ref().unwrap(),
|
||||
&**self.indexes_to_supply.bitcoin.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(indexes_to_realized_price_extra) = self.indexes_to_realized_price_extra.as_mut()
|
||||
{
|
||||
indexes_to_realized_price_extra.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched.as_ref().unwrap(),
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(
|
||||
self.indexes_to_realized_price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_last(),
|
||||
),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
vec![
|
||||
&self.height_to_supply as &dyn AnyCollectableVec,
|
||||
&self.height_to_utxo_count,
|
||||
],
|
||||
self.height_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
|
||||
self.indexes_to_supply.vecs(),
|
||||
self.indexes_to_utxo_count.vecs(),
|
||||
self.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_realized_price
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_realized_price_extra
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Vecs {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
starting_height: self.starting_height,
|
||||
state: CohortState::default(),
|
||||
|
||||
height_to_realized_cap: self.height_to_realized_cap.clone(),
|
||||
indexes_to_realized_cap: self.indexes_to_realized_cap.clone(),
|
||||
height_to_supply: self.height_to_supply.clone(),
|
||||
indexes_to_supply: self.indexes_to_supply.clone(),
|
||||
height_to_utxo_count: self.height_to_utxo_count.clone(),
|
||||
indexes_to_utxo_count: self.indexes_to_utxo_count.clone(),
|
||||
|
||||
indexes_to_realized_price: self.indexes_to_realized_price.clone(),
|
||||
indexes_to_realized_price_extra: self.indexes_to_realized_price_extra.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,14 @@
|
||||
use std::ops::{Add, Div, Mul};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Add, Div, Mul},
|
||||
};
|
||||
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::Sats;
|
||||
use super::{Sats, StoredF64};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
#[derive(Debug, Default, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize)]
|
||||
pub struct Bitcoin(f64);
|
||||
|
||||
impl Add for Bitcoin {
|
||||
@@ -53,6 +44,12 @@ impl From<f64> for Bitcoin {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredF64> for Bitcoin {
|
||||
fn from(value: StoredF64) -> Self {
|
||||
Self(*value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Bitcoin> for f64 {
|
||||
fn from(value: Bitcoin) -> Self {
|
||||
value.0
|
||||
@@ -65,11 +62,34 @@ impl From<usize> for Bitcoin {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Bitcoin {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => true,
|
||||
(true, false) => false,
|
||||
(false, true) => false,
|
||||
(false, false) => self.0 == other.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Bitcoin {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Bitcoin {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.0).unwrap()
|
||||
impl PartialOrd for Bitcoin {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Bitcoin {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => Ordering::Equal,
|
||||
(true, false) => Ordering::Less,
|
||||
(false, true) => Ordering::Greater,
|
||||
(false, false) => self.0.partial_cmp(&other.0).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use std::ops::{Add, Div};
|
||||
use std::ops::{Add, Div, Mul};
|
||||
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::Dollars;
|
||||
|
||||
#[derive(
|
||||
@@ -59,3 +61,38 @@ impl Div<usize> for Cents {
|
||||
Self(self.0 / rhs as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for Cents {
|
||||
fn from(value: u128) -> Self {
|
||||
if value > u64::MAX as u128 {
|
||||
panic!("u128 bigger than u64")
|
||||
}
|
||||
Self(value as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Cents> for u128 {
|
||||
fn from(value: Cents) -> Self {
|
||||
value.0 as u128
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Cents> for Cents {
|
||||
type Output = Cents;
|
||||
fn mul(self, rhs: Cents) -> Self::Output {
|
||||
Self(self.0 * rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<usize> for Cents {
|
||||
type Output = Cents;
|
||||
fn mul(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 * rhs as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Cents {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
self.0.checked_sub(rhs.0).map(Cents::from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ impl Date {
|
||||
pub const INDEX_ZERO_: Date_ = Date_::constant(2009, 1, 3);
|
||||
pub const INDEX_ONE: Self = Self(20090109);
|
||||
pub const INDEX_ONE_: Date_ = Date_::constant(2009, 1, 9);
|
||||
pub const MIN_RATIO: Self = Self(20120101);
|
||||
|
||||
pub fn new(year: u16, month: u8, day: u8) -> Self {
|
||||
Self(year as u32 * 1_00_00 + month as u32 * 1_00 + day as u32)
|
||||
|
||||
@@ -1,27 +1,37 @@
|
||||
use std::ops::{Add, Div, Mul};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
f64,
|
||||
ops::{Add, AddAssign, Div, Mul},
|
||||
};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::{Bitcoin, Cents, Sats};
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Bitcoin, Cents, Close, Sats, StoredF32, StoredF64};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
Deref,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
Debug, Default, Clone, Copy, Deref, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
|
||||
)]
|
||||
pub struct Dollars(f64);
|
||||
|
||||
impl Dollars {
|
||||
pub const ZERO: Self = Self(0.0);
|
||||
pub const NAN: Self = Self(f64::NAN);
|
||||
|
||||
pub const fn mint(dollars: f64) -> Self {
|
||||
Self(dollars)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for Dollars {
|
||||
fn from(value: f32) -> Self {
|
||||
Self(value as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Dollars {
|
||||
fn from(value: f64) -> Self {
|
||||
Self(value)
|
||||
@@ -34,12 +44,24 @@ impl From<Cents> for Dollars {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dollars> for f32 {
|
||||
fn from(value: Dollars) -> Self {
|
||||
value.0 as f32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dollars> for f64 {
|
||||
fn from(value: Dollars) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Close<Dollars>> for Dollars {
|
||||
fn from(value: Close<Dollars>) -> Self {
|
||||
Self(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Dollars {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as f64)
|
||||
@@ -53,27 +75,167 @@ impl Add for Dollars {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Dollars> for Dollars {
|
||||
type Output = StoredF64;
|
||||
fn div(self, rhs: Dollars) -> Self::Output {
|
||||
if self.is_nan() {
|
||||
StoredF64::from(self.0)
|
||||
} else {
|
||||
StoredF64::from(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Close<Dollars>> for Dollars {
|
||||
type Output = StoredF64;
|
||||
fn div(self, rhs: Close<Dollars>) -> Self::Output {
|
||||
if self.is_nan() {
|
||||
StoredF64::from(self.0)
|
||||
} else {
|
||||
StoredF64::from(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Dollars> for Close<Dollars> {
|
||||
type Output = StoredF64;
|
||||
fn div(self, rhs: Dollars) -> Self::Output {
|
||||
if self.is_nan() {
|
||||
StoredF64::from(self.0)
|
||||
} else {
|
||||
StoredF64::from(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self::from(Cents::from(self) / rhs)
|
||||
if self.is_nan() {
|
||||
self
|
||||
} else {
|
||||
Self::from(Cents::from(self) / rhs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Bitcoin> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Bitcoin) -> Self::Output {
|
||||
if self.is_nan() {
|
||||
self
|
||||
} else {
|
||||
Self(f64::from(self) / f64::from(rhs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Bitcoin> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: Bitcoin) -> Self::Output {
|
||||
if self.is_nan() {
|
||||
self
|
||||
} else {
|
||||
Self::from(Cents::from(
|
||||
u128::from(Sats::from(rhs)) * u128::from(Cents::from(self))
|
||||
/ u128::from(Sats::ONE_BTC),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF32> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF32) -> Self::Output {
|
||||
if rhs.is_nan() {
|
||||
self
|
||||
} else {
|
||||
Self::from(Cents::from(Self::from(self.0 * *rhs as f64)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<usize> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: usize) -> Self::Output {
|
||||
if self.is_nan() {
|
||||
self
|
||||
} else {
|
||||
Self::from(Cents::from(self) * rhs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for Dollars {
|
||||
fn from(value: u128) -> Self {
|
||||
Self::from(Cents::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Close<Dollars>> for u128 {
|
||||
fn from(value: Close<Dollars>) -> Self {
|
||||
u128::from(*value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dollars> for u128 {
|
||||
fn from(value: Dollars) -> Self {
|
||||
u128::from(Cents::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Dollars {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = Dollars::from(Cents::from(*self) + Cents::from(rhs));
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub for Dollars {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
if self.is_nan() {
|
||||
Some(self)
|
||||
} else {
|
||||
Cents::from(self)
|
||||
.checked_sub(Cents::from(rhs))
|
||||
.map(Dollars::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<usize> for Dollars {
|
||||
fn checked_sub(self, rhs: usize) -> Option<Self> {
|
||||
Some(Self(self.0 - rhs as f64))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Dollars {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => true,
|
||||
(true, false) => false,
|
||||
(false, true) => false,
|
||||
(false, false) => self.0 == other.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Dollars {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Dollars {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.0).unwrap()
|
||||
impl PartialOrd for Dollars {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Bitcoin> for Dollars {
|
||||
type Output = Dollars;
|
||||
fn mul(self, rhs: Bitcoin) -> Self::Output {
|
||||
Self::from(Cents::from(
|
||||
u64::from(Sats::from(rhs)) * u64::from(Cents::from(self)) / u64::from(Sats::ONE_BTC),
|
||||
))
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Dollars {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => Ordering::Equal,
|
||||
(true, false) => Ordering::Less,
|
||||
(false, true) => Ordering::Greater,
|
||||
(false, false) => self.0.partial_cmp(&other.0).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
use std::ops::{Add, Div};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Add, Div},
|
||||
};
|
||||
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::{Sats, StoredUsize};
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Serialize,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout)]
|
||||
pub struct Feerate(f32);
|
||||
|
||||
impl From<(Sats, StoredUsize)> for Feerate {
|
||||
@@ -56,11 +48,34 @@ impl From<usize> for Feerate {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Feerate {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => true,
|
||||
(true, false) => false,
|
||||
(false, true) => false,
|
||||
(false, false) => self.0 == other.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Feerate {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Feerate {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.0).unwrap()
|
||||
impl PartialOrd for Feerate {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Feerate {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => Ordering::Equal,
|
||||
(true, false) => Ordering::Less,
|
||||
(false, true) => Ordering::Greater,
|
||||
(false, false) => self.0.partial_cmp(&other.0).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,12 @@ use super::Height;
|
||||
)]
|
||||
pub struct HalvingEpoch(u8);
|
||||
|
||||
impl HalvingEpoch {
|
||||
pub fn new(value: u8) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for HalvingEpoch {
|
||||
fn from(value: u8) -> Self {
|
||||
Self(value)
|
||||
|
||||
@@ -24,6 +24,7 @@ mod outputtypeindex;
|
||||
mod quarterindex;
|
||||
mod rawlocktime;
|
||||
mod sats;
|
||||
mod stored_f32;
|
||||
mod stored_f64;
|
||||
mod stored_u32;
|
||||
mod stored_u64;
|
||||
@@ -67,6 +68,7 @@ pub use outputtypeindex::*;
|
||||
pub use quarterindex::*;
|
||||
pub use rawlocktime::*;
|
||||
pub use sats::*;
|
||||
pub use stored_f32::*;
|
||||
pub use stored_f64::*;
|
||||
pub use stored_u8::*;
|
||||
pub use stored_u32::*;
|
||||
@@ -83,3 +85,5 @@ pub use vout::*;
|
||||
pub use weekindex::*;
|
||||
pub use weight::*;
|
||||
pub use yearindex::*;
|
||||
|
||||
pub use rlimit;
|
||||
|
||||
@@ -453,6 +453,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<f32> for Close<T>
|
||||
where
|
||||
T: From<f32>,
|
||||
{
|
||||
fn from(value: f32) -> Self {
|
||||
Self(T::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<f64> for Close<T>
|
||||
where
|
||||
T: From<f64>,
|
||||
@@ -462,6 +471,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Close<T>> for f32
|
||||
where
|
||||
f32: From<T>,
|
||||
{
|
||||
fn from(value: Close<T>) -> Self {
|
||||
Self::from(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Close<T>> for f64
|
||||
where
|
||||
f64: From<T>,
|
||||
|
||||
@@ -32,6 +32,46 @@ pub enum OutputType {
|
||||
Unknown = 255,
|
||||
}
|
||||
|
||||
impl OutputType {
|
||||
pub fn is_spendable(&self) -> bool {
|
||||
match self {
|
||||
Self::P2PK65 => true,
|
||||
Self::P2PK33 => true,
|
||||
Self::P2PKH => true,
|
||||
Self::P2MS => true,
|
||||
Self::P2SH => true,
|
||||
Self::OpReturn => false,
|
||||
Self::P2WPKH => true,
|
||||
Self::P2WSH => true,
|
||||
Self::P2TR => true,
|
||||
Self::P2A => true,
|
||||
Self::Empty => true,
|
||||
Self::Unknown => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_unspendable(&self) -> bool {
|
||||
!self.is_spendable()
|
||||
}
|
||||
|
||||
pub fn as_vec() -> Vec<Self> {
|
||||
vec![
|
||||
Self::P2PK65,
|
||||
Self::P2PK33,
|
||||
Self::P2PKH,
|
||||
Self::P2MS,
|
||||
Self::P2SH,
|
||||
Self::OpReturn,
|
||||
Self::P2WPKH,
|
||||
Self::P2WSH,
|
||||
Self::P2TR,
|
||||
Self::P2A,
|
||||
Self::Empty,
|
||||
Self::Unknown,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ScriptBuf> for OutputType {
|
||||
fn from(script: &ScriptBuf) -> Self {
|
||||
if script.is_p2pk() {
|
||||
|
||||
@@ -28,14 +28,24 @@ use super::{Bitcoin, Cents, Dollars, Height};
|
||||
)]
|
||||
pub struct Sats(u64);
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)]
|
||||
impl Sats {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const MAX: Self = Self(u64::MAX);
|
||||
pub const ONE_BTC: Self = Self(100_000_000);
|
||||
pub const ONE_BTC: Self = Self(1_00_000_000);
|
||||
pub const FIFTY_BTC: Self = Self(50_00_000_000);
|
||||
|
||||
pub fn new(sats: u64) -> Self {
|
||||
Self(sats)
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
*self == Self::ZERO
|
||||
}
|
||||
|
||||
pub fn is_not_zero(&self) -> bool {
|
||||
*self != Self::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Sats {
|
||||
@@ -134,6 +144,12 @@ impl From<Sats> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sats> for usize {
|
||||
fn from(value: Sats) -> Self {
|
||||
value.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Amount> for Sats {
|
||||
fn from(value: Amount) -> Self {
|
||||
Self(value.to_sat())
|
||||
@@ -156,3 +172,18 @@ impl From<Sats> for u64 {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u128> for Sats {
|
||||
fn from(value: u128) -> Self {
|
||||
if value > u64::MAX as u128 {
|
||||
panic!("u128 bigger than u64")
|
||||
}
|
||||
Self(value as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sats> for u128 {
|
||||
fn from(value: Sats) -> Self {
|
||||
value.0 as u128
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Add, Div, Mul, Sub},
|
||||
};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::CheckedSub;
|
||||
|
||||
use super::{Dollars, StoredF64};
|
||||
|
||||
#[derive(
|
||||
Debug, Deref, Default, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
|
||||
)]
|
||||
pub struct StoredF32(f32);
|
||||
|
||||
impl From<f32> for StoredF32 {
|
||||
fn from(value: f32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for StoredF32 {
|
||||
fn from(value: f64) -> Self {
|
||||
Self(value as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredF64> for StoredF32 {
|
||||
fn from(value: StoredF64) -> Self {
|
||||
Self(*value as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for StoredF32 {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<StoredF32> for StoredF32 {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
Some(Self(self.0 - rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredF32 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredF32> for f32 {
|
||||
fn from(value: StoredF32) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Dollars> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Dollars) -> Self::Output {
|
||||
Self::from(self.0 as f64 / *rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<StoredF32> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: StoredF32) -> Self::Output {
|
||||
Self::from(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<usize> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 * rhs as f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF32> for usize {
|
||||
type Output = StoredF32;
|
||||
fn mul(self, rhs: StoredF32) -> Self::Output {
|
||||
StoredF32(self as f32 * rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<StoredF32> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn sub(self, rhs: StoredF32) -> Self::Output {
|
||||
Self(self.0 - rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for StoredF32 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => true,
|
||||
(true, false) => false,
|
||||
(false, true) => false,
|
||||
(false, false) => self.0 == other.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for StoredF32 {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl PartialOrd for StoredF32 {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for StoredF32 {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => Ordering::Equal,
|
||||
(true, false) => Ordering::Less,
|
||||
(false, true) => Ordering::Greater,
|
||||
(false, false) => self.0.partial_cmp(&other.0).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::ops::{Add, Div};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Add, Div, Mul},
|
||||
};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
@@ -7,17 +10,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
use crate::CheckedSub;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
Debug, Deref, Default, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
|
||||
)]
|
||||
pub struct StoredF64(f64);
|
||||
|
||||
@@ -39,6 +32,13 @@ impl CheckedSub<StoredF64> for StoredF64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<usize> for StoredF64 {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 * rhs as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for StoredF64 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
@@ -59,11 +59,40 @@ impl From<StoredF64> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<usize> for StoredF64 {
|
||||
fn checked_sub(self, rhs: usize) -> Option<Self> {
|
||||
Some(Self(self.0 - rhs as f64))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for StoredF64 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => true,
|
||||
(true, false) => false,
|
||||
(false, true) => false,
|
||||
(false, false) => self.0 == other.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for StoredF64 {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for StoredF64 {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.0).unwrap()
|
||||
impl PartialOrd for StoredF64 {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for StoredF64 {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => Ordering::Equal,
|
||||
(true, false) => Ordering::Less,
|
||||
(false, true) => Ordering::Greater,
|
||||
(false, false) => self.0.partial_cmp(&other.0).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use super::{
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Default,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::{Add, Div};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
@@ -15,7 +15,9 @@ use super::{
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
DerefMut,
|
||||
Clone,
|
||||
Default,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::ops::{Add, Div};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Add, Div},
|
||||
};
|
||||
|
||||
use derive_deref::Deref;
|
||||
use jiff::{civil::date, tz::TimeZone};
|
||||
@@ -26,6 +29,8 @@ use super::Date;
|
||||
)]
|
||||
pub struct Timestamp(u32);
|
||||
|
||||
const ONE_DAY_IN_SEC: i64 = 24 * 60 * 60;
|
||||
|
||||
impl Timestamp {
|
||||
pub const ZERO: Self = Self(0);
|
||||
|
||||
@@ -34,10 +39,28 @@ impl Timestamp {
|
||||
}
|
||||
|
||||
pub fn floor_seconds(self) -> Self {
|
||||
let t = jiff::Timestamp::from(self).to_zoned(TimeZone::UTC);
|
||||
let d = jiff::civil::DateTime::from(t);
|
||||
let d = date(d.year(), d.month(), d.day()).at(d.hour(), d.minute(), 0, 0);
|
||||
Self::from(d.to_zoned(TimeZone::UTC).unwrap().timestamp())
|
||||
let zoned = jiff::Timestamp::from(self).to_zoned(TimeZone::UTC);
|
||||
let date_time = jiff::civil::DateTime::from(zoned);
|
||||
let trunc_date_time = date(date_time.year(), date_time.month(), date_time.day()).at(
|
||||
date_time.hour(),
|
||||
date_time.minute(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
Self::from(trunc_date_time.to_zoned(TimeZone::UTC).unwrap().timestamp())
|
||||
}
|
||||
|
||||
pub fn difference_in_days_between(&self, other: Self) -> usize {
|
||||
match self.cmp(&other) {
|
||||
Ordering::Equal => 0,
|
||||
Ordering::Greater => other.difference_in_days_between(*self),
|
||||
Ordering::Less => {
|
||||
(jiff::Timestamp::from(*self)
|
||||
.duration_until(jiff::Timestamp::from(other))
|
||||
.as_secs()
|
||||
/ ONE_DAY_IN_SEC) as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,14 @@ use rlimit::{Resource, getrlimit};
|
||||
|
||||
pub fn setrlimit() -> io::Result<()> {
|
||||
let no_file_limit = getrlimit(Resource::NOFILE)?;
|
||||
rlimit::setrlimit(Resource::NOFILE, no_file_limit.0.max(210_000), no_file_limit.1)?;
|
||||
rlimit::setrlimit(
|
||||
Resource::NOFILE,
|
||||
no_file_limit.0.max(210_000),
|
||||
no_file_limit.1,
|
||||
)?;
|
||||
|
||||
// let no_stack = getrlimit(Resource::STACK)?;
|
||||
// rlimit::setrlimit(Resource::STACK, no_stack.1, no_stack.1)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
brk_logger = { workspace = true }
|
||||
ctrlc = { version = "3.4.6", features = ["termination"] }
|
||||
ctrlc = { version = "3.4.7", features = ["termination"] }
|
||||
log = { workspace = true }
|
||||
|
||||
@@ -238,4 +238,9 @@ impl Binance {
|
||||
fn url(query: &str) -> String {
|
||||
format!("https://api.binance.com/api/v3/uiKlines?symbol=BTCUSDT&{query}")
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self._1d.take();
|
||||
self._1mn.take();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ impl Kibo {
|
||||
.unwrap()
|
||||
.get(usize::from(height.checked_sub(key).unwrap()))
|
||||
.cloned()
|
||||
.ok_or(color_eyre::eyre::Error::msg("Couldn't find height in kibo"))
|
||||
.ok_or(eyre!("Couldn't find height in kibo"))
|
||||
}
|
||||
|
||||
fn fetch_height_prices(height: Height) -> color_eyre::Result<Vec<OHLCCents>> {
|
||||
@@ -147,4 +147,9 @@ impl Kibo {
|
||||
Close::new(get_value("close")?),
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.height_to_ohlc_vec.clear();
|
||||
self.year_to_date_to_ohlc.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,4 +129,9 @@ impl Kraken {
|
||||
fn url(interval: usize) -> String {
|
||||
format!("https://api.kraken.com/0/public/OHLC?pair=XBTUSD&interval={interval}")
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self._1d.take();
|
||||
self._1mn.take();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#![doc = include_str!("../examples/main.rs")]
|
||||
#![doc = "```"]
|
||||
|
||||
use std::{collections::BTreeMap, fs, path::Path};
|
||||
use std::{collections::BTreeMap, fs, path::Path, thread::sleep, time::Duration};
|
||||
|
||||
use brk_core::{Cents, Close, Date, Dollars, Height, High, Low, OHLCCents, Open, Timestamp};
|
||||
use color_eyre::eyre::Error;
|
||||
@@ -35,8 +35,14 @@ impl Fetcher {
|
||||
pub fn get_date(&mut self, date: Date) -> color_eyre::Result<OHLCCents> {
|
||||
self.kraken
|
||||
.get_from_1d(&date)
|
||||
.or_else(|_| self.binance.get_from_1d(&date))
|
||||
.or_else(|_| self.kibo.get_from_date(&date))
|
||||
.or_else(|_| {
|
||||
// eprintln!("{e}");
|
||||
self.binance.get_from_1d(&date)
|
||||
})
|
||||
.or_else(|e| {
|
||||
eprintln!("{e}");
|
||||
self.kibo.get_from_date(&date)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_height(
|
||||
@@ -44,6 +50,16 @@ impl Fetcher {
|
||||
height: Height,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
) -> color_eyre::Result<OHLCCents> {
|
||||
self.get_height_(height, timestamp, previous_timestamp, 0)
|
||||
}
|
||||
|
||||
fn get_height_(
|
||||
&mut self,
|
||||
height: Height,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
tries: usize,
|
||||
) -> color_eyre::Result<OHLCCents> {
|
||||
let timestamp = timestamp.floor_seconds();
|
||||
|
||||
@@ -57,12 +73,24 @@ impl Fetcher {
|
||||
.kraken
|
||||
.get_from_1mn(timestamp, previous_timestamp)
|
||||
.unwrap_or_else(|_| {
|
||||
// eprintln!("{e}");
|
||||
self.binance
|
||||
.get_from_1mn(timestamp, previous_timestamp)
|
||||
.unwrap_or_else(|_| {
|
||||
self.kibo.get_from_height(height).unwrap_or_else(|e| {
|
||||
// eprintln!("{e}");
|
||||
self.kibo.get_from_height(height).unwrap_or_else(|_| {
|
||||
sleep(Duration::from_secs(30));
|
||||
|
||||
if tries < 8 * 60 * 2 {
|
||||
self.clear();
|
||||
|
||||
return self
|
||||
.get_height_(height, timestamp, previous_timestamp, tries + 1)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let date = Date::from(timestamp);
|
||||
eprintln!("{e}");
|
||||
// eprintln!("{e}");
|
||||
panic!(
|
||||
"
|
||||
Can't find the price for: height: {height} - date: {date}
|
||||
@@ -130,4 +158,10 @@ How to fix this:
|
||||
|
||||
Ok(final_ohlc)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.binance.clear();
|
||||
self.kibo.clear();
|
||||
self.kraken.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -744,18 +744,10 @@ impl Indexer {
|
||||
self.vecs.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn mut_vecs(&mut self) -> &mut Vecs {
|
||||
self.vecs.as_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn stores(&self) -> &Stores {
|
||||
self.stores.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn mut_stores(&mut self) -> &mut Stores {
|
||||
self.stores.as_mut().unwrap()
|
||||
}
|
||||
|
||||
pub fn keyspace(&self) -> &TransactionalKeyspace {
|
||||
&self.stores().keyspace
|
||||
}
|
||||
|
||||
@@ -68,222 +68,261 @@ impl Vecs {
|
||||
|
||||
Ok(Self {
|
||||
emptyoutputindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("emptyoutputindex_to_txindex"),
|
||||
path,
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_blockhash: IndexedVec::forced_import(
|
||||
&path.join("height_to_blockhash"),
|
||||
path,
|
||||
"blockhash",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
height_to_difficulty: IndexedVec::forced_import(
|
||||
&path.join("height_to_difficulty"),
|
||||
path,
|
||||
"difficulty",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_emptyoutputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_emptyoutputindex"),
|
||||
path,
|
||||
"first_emptyoutputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_inputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_inputindex"),
|
||||
path,
|
||||
"first_inputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_opreturnindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_opreturnindex"),
|
||||
path,
|
||||
"first_opreturnindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_outputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_outputindex"),
|
||||
path,
|
||||
"first_outputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2aindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2aindex"),
|
||||
path,
|
||||
"first_p2aindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2msindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2msindex"),
|
||||
path,
|
||||
"first_p2msindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2pk33index: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2pk33index"),
|
||||
path,
|
||||
"first_p2pk33index",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2pk65index: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2pk65index"),
|
||||
path,
|
||||
"first_p2pk65index",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2pkhindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2pkhindex"),
|
||||
path,
|
||||
"first_p2pkhindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2shindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2shindex"),
|
||||
path,
|
||||
"first_p2shindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2trindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2trindex"),
|
||||
path,
|
||||
"first_p2trindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2wpkhindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2wpkhindex"),
|
||||
path,
|
||||
"first_p2wpkhindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_p2wshindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_p2wshindex"),
|
||||
path,
|
||||
"first_p2wshindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_txindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_txindex"),
|
||||
path,
|
||||
"first_txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_first_unknownoutputindex: IndexedVec::forced_import(
|
||||
&path.join("height_to_first_unknownoutputindex"),
|
||||
path,
|
||||
"first_unknownoutputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_timestamp: IndexedVec::forced_import(
|
||||
&path.join("height_to_timestamp"),
|
||||
path,
|
||||
"timestamp",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_total_size: IndexedVec::forced_import(
|
||||
&path.join("height_to_total_size"),
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_weight: IndexedVec::forced_import(
|
||||
&path.join("height_to_weight"),
|
||||
path,
|
||||
"total_size",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
height_to_weight: IndexedVec::forced_import(path, "weight", Version::ZERO, compressed)?,
|
||||
inputindex_to_outputindex: IndexedVec::forced_import(
|
||||
&path.join("inputindex_to_outputindex"),
|
||||
path,
|
||||
"outputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
opreturnindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("opreturnindex_to_txindex"),
|
||||
path,
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
outputindex_to_outputtype: IndexedVec::forced_import(
|
||||
&path.join("outputindex_to_outputtype"),
|
||||
path,
|
||||
"outputtype",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
outputindex_to_outputtypeindex: IndexedVec::forced_import(
|
||||
&path.join("outputindex_to_outputtypeindex"),
|
||||
path,
|
||||
"outputtypeindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
outputindex_to_value: IndexedVec::forced_import(
|
||||
&path.join("outputindex_to_value"),
|
||||
path,
|
||||
"value",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2aindex_to_p2abytes: IndexedVec::forced_import(
|
||||
&path.join("p2aindex_to_p2abytes"),
|
||||
path,
|
||||
"p2abytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2msindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("p2msindex_to_txindex"),
|
||||
path,
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
p2pk33index_to_p2pk33bytes: IndexedVec::forced_import(
|
||||
&path.join("p2pk33index_to_p2pk33bytes"),
|
||||
path,
|
||||
"p2pk33bytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2pk65index_to_p2pk65bytes: IndexedVec::forced_import(
|
||||
&path.join("p2pk65index_to_p2pk65bytes"),
|
||||
path,
|
||||
"p2pk65bytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2pkhindex_to_p2pkhbytes: IndexedVec::forced_import(
|
||||
&path.join("p2pkhindex_to_p2pkhbytes"),
|
||||
path,
|
||||
"p2pkhbytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2shindex_to_p2shbytes: IndexedVec::forced_import(
|
||||
&path.join("p2shindex_to_p2shbytes"),
|
||||
path,
|
||||
"p2shbytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2trindex_to_p2trbytes: IndexedVec::forced_import(
|
||||
&path.join("p2trindex_to_p2trbytes"),
|
||||
path,
|
||||
"p2trbytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2wpkhindex_to_p2wpkhbytes: IndexedVec::forced_import(
|
||||
&path.join("p2wpkhindex_to_p2wpkhbytes"),
|
||||
path,
|
||||
"p2wpkhbytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
p2wshindex_to_p2wshbytes: IndexedVec::forced_import(
|
||||
&path.join("p2wshindex_to_p2wshbytes"),
|
||||
path,
|
||||
"p2wshbytes",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
txindex_to_base_size: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_base_size"),
|
||||
path,
|
||||
"base_size",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_first_inputindex: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_first_inputindex"),
|
||||
path,
|
||||
"first_inputindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_first_outputindex: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_first_outputindex"),
|
||||
path,
|
||||
"first_outputindex",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
txindex_to_is_explicitly_rbf: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_is_explicitly_rbf"),
|
||||
path,
|
||||
"is_explicitly_rbf",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_rawlocktime: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_rawlocktime"),
|
||||
path,
|
||||
"rawlocktime",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_total_size: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_total_size"),
|
||||
path,
|
||||
"total_size",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
txindex_to_txid: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_txid"),
|
||||
path,
|
||||
"txid",
|
||||
Version::ZERO,
|
||||
Compressed::NO,
|
||||
)?,
|
||||
txindex_to_txversion: IndexedVec::forced_import(
|
||||
&path.join("txindex_to_txversion"),
|
||||
path,
|
||||
"txversion",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
unknownoutputindex_to_txindex: IndexedVec::forced_import(
|
||||
&path.join("unknownoutputindex_to_txindex"),
|
||||
path,
|
||||
"txindex",
|
||||
Version::ZERO,
|
||||
compressed,
|
||||
)?,
|
||||
|
||||
@@ -84,9 +84,8 @@ impl Parser {
|
||||
thread::spawn(move || {
|
||||
let xor_bytes = xor_bytes;
|
||||
|
||||
blk_index_to_blk_path
|
||||
.range(blk_index..)
|
||||
.try_for_each(move |(blk_index, blk_path)| {
|
||||
let _ = blk_index_to_blk_path.range(blk_index..).try_for_each(
|
||||
move |(blk_index, blk_path)| {
|
||||
let mut xor_i = XORIndex::default();
|
||||
|
||||
let blk_index = *blk_index;
|
||||
@@ -139,7 +138,8 @@ impl Parser {
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
thread::spawn(move || {
|
||||
@@ -177,7 +177,7 @@ impl Parser {
|
||||
|
||||
// Sending in bulk to not lock threads in standby
|
||||
drain_and_send(&mut bulk)
|
||||
});
|
||||
})?;
|
||||
|
||||
drain_and_send(&mut bulk)
|
||||
});
|
||||
@@ -187,7 +187,7 @@ impl Parser {
|
||||
|
||||
let mut future_blocks = BTreeMap::default();
|
||||
|
||||
recv_block
|
||||
let _ = recv_block
|
||||
.iter()
|
||||
.try_for_each(|(blk_metadata, block)| -> ControlFlow<(), _> {
|
||||
let hash = block.block_hash();
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::fmt::{self, Debug};
|
||||
|
||||
use color_eyre::eyre::eyre;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Index {
|
||||
DateIndex,
|
||||
DecadeIndex,
|
||||
|
||||
@@ -16,7 +16,11 @@ impl<'a> VecTrees<'a> {
|
||||
pub fn insert(&mut self, vec: &'a dyn AnyCollectableVec) {
|
||||
let name = vec.name();
|
||||
let split = name.split("_to_").collect::<Vec<_>>();
|
||||
if split.len() != 2 {
|
||||
if split.len() != 2
|
||||
&& !(split.len() == 3
|
||||
&& (split.get(1) == Some(&"up")
|
||||
|| split.get(1).is_some_and(|s| s.starts_with("from"))))
|
||||
{
|
||||
dbg!(&name, &split);
|
||||
panic!();
|
||||
}
|
||||
@@ -35,12 +39,12 @@ impl<'a> VecTrees<'a> {
|
||||
dbg!(&name, split[0], index.to_string());
|
||||
panic!();
|
||||
}
|
||||
let key = split[1].to_string().replace("_", "-");
|
||||
let key = split[1..].join("_to_").to_string().replace("_", "-");
|
||||
let prev = self
|
||||
.id_to_index_to_vec
|
||||
.entry(key.clone())
|
||||
.or_default()
|
||||
.insert(index.clone(), vec);
|
||||
.insert(index, vec);
|
||||
if prev.is_some() {
|
||||
dbg!(&key, str, name);
|
||||
panic!()
|
||||
|
||||
@@ -23,9 +23,9 @@ color-eyre = { workspace = true }
|
||||
jiff = { workspace = true }
|
||||
log = { workspace = true }
|
||||
minreq = { workspace = true }
|
||||
oxc = { version = "0.68.1", features = ["codegen", "minifier"] }
|
||||
oxc = { version = "0.72.0", features = ["codegen", "minifier"] }
|
||||
serde = { workspace = true }
|
||||
tokio = { version = "1.45.0", features = ["full"] }
|
||||
tower-http = { version = "0.6.3", features = ["compression-full", "trace"] }
|
||||
zip = "2.6.1"
|
||||
tower-http = { version = "0.6.4", features = ["compression-full", "trace"] }
|
||||
zip = "4.0.0"
|
||||
tracing = "0.1.41"
|
||||
|
||||
@@ -57,15 +57,15 @@ impl DTS for Query<'static> {
|
||||
|
||||
contents += "\n\nexport function createVecIdToIndexes() {\n";
|
||||
|
||||
contents += &indexes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i_of_i, i)| {
|
||||
// let lowered = i.to_string().to_lowercase();
|
||||
format!(" const {i} = /** @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!(" const {i} = /** @satisfies {{{i}}} */ ({i_of_i});",)
|
||||
// })
|
||||
// .collect::<Vec<_>>()
|
||||
// .join("\n");
|
||||
|
||||
contents += "\n\n return /** @type {const} */ ({\n";
|
||||
|
||||
@@ -75,18 +75,12 @@ impl DTS for Query<'static> {
|
||||
.for_each(|(id, index_to_vec)| {
|
||||
let indexes = index_to_vec
|
||||
.keys()
|
||||
.map(|i| i.to_string())
|
||||
.map(|i| (*i as u8).to_string())
|
||||
// .map(|i| i.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
contents += &format!(
|
||||
" {}: [{indexes}],\n",
|
||||
if id.contains("-") {
|
||||
format!("\"{id}\"")
|
||||
} else {
|
||||
id.to_owned()
|
||||
}
|
||||
);
|
||||
contents += &format!(" \"{id}\": [{indexes}],\n");
|
||||
});
|
||||
|
||||
contents += " });\n";
|
||||
|
||||
@@ -38,7 +38,7 @@ fn any_handler(
|
||||
.expect("Should never reach here is websites_path is None")
|
||||
.join(app_state.website.to_folder_name());
|
||||
|
||||
let response = if let Some(path) = path.as_ref() {
|
||||
if let Some(path) = path.as_ref() {
|
||||
let path = path.0.replace("..", "").replace("\\", "");
|
||||
|
||||
let mut path = website_path.join(&path);
|
||||
@@ -62,9 +62,7 @@ fn any_handler(
|
||||
path_to_response(&headers, &path)
|
||||
} else {
|
||||
path_to_response(&headers, &website_path.join("index.html"))
|
||||
};
|
||||
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
fn path_to_response(headers: &HeaderMap, path: &Path) -> Response {
|
||||
|
||||
@@ -12,7 +12,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
{
|
||||
let mut vec: StoredVec<usize, u32> =
|
||||
StoredVec::forced_import(Path::new("./vec"), version, compressed)?;
|
||||
StoredVec::forced_import(Path::new("."), "vec", version, compressed)?;
|
||||
|
||||
(0..21_u32).for_each(|v| {
|
||||
vec.push(v);
|
||||
@@ -28,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
{
|
||||
let mut vec: StoredVec<usize, u32> =
|
||||
StoredVec::forced_import(Path::new("./vec"), version, compressed)?;
|
||||
StoredVec::forced_import(Path::new("."), "vec", version, compressed)?;
|
||||
let mut iter = vec.into_iter();
|
||||
|
||||
dbg!(iter.get(0));
|
||||
@@ -54,7 +54,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
{
|
||||
let mut vec: StoredVec<usize, u32> =
|
||||
StoredVec::forced_import(Path::new("./vec"), version, compressed)?;
|
||||
StoredVec::forced_import(Path::new("."), "vec", version, compressed)?;
|
||||
let mut iter = vec.into_iter();
|
||||
|
||||
dbg!(iter.get(0));
|
||||
|
||||
@@ -19,6 +19,11 @@ impl<'a, T> UnsafeSlice<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// SAFETY: It is UB
|
||||
pub fn get(&self, i: usize) -> *mut T {
|
||||
self.0[i].get()
|
||||
}
|
||||
|
||||
pub fn copy_slice(&self, start: usize, slice: &[T])
|
||||
where
|
||||
T: Copy,
|
||||
|
||||
@@ -20,6 +20,10 @@ impl Version {
|
||||
pub const ONE: Self = Self(1);
|
||||
pub const TWO: Self = Self(2);
|
||||
|
||||
pub const fn new(v: u32) -> Self {
|
||||
Self(v)
|
||||
}
|
||||
|
||||
pub fn write(&self, path: &Path) -> Result<(), io::Error> {
|
||||
fs::write(path, self.as_bytes())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ pub trait AnyVec: Send + Sync {
|
||||
self.len() == 0
|
||||
}
|
||||
fn modified_time(&self) -> Result<Duration>;
|
||||
fn index_type_to_string(&self) -> &str;
|
||||
fn index_type_to_string(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait AnyIterableVec<I, T>: AnyVec {
|
||||
|
||||
@@ -11,7 +11,7 @@ where
|
||||
fn collect_range(&self, from: Option<usize>, to: Option<usize>) -> Result<Vec<T>> {
|
||||
let len = self.len();
|
||||
let from = from.unwrap_or_default();
|
||||
let to = to.map_or(len, |i| i.min(len));
|
||||
let to = to.map_or(len, |to| to.min(len));
|
||||
|
||||
if from >= len || from >= to {
|
||||
return Ok(vec![]);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
ops::Add,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::{Error, Result};
|
||||
|
||||
@@ -20,8 +24,14 @@ where
|
||||
{
|
||||
fn unwrap_to_usize(self) -> usize;
|
||||
fn to_usize(self) -> Result<usize>;
|
||||
fn to_string<'a>() -> &'a str;
|
||||
fn to_string() -> String;
|
||||
fn decremented(self) -> Option<Self>;
|
||||
fn to_folder_name(value_name: &str) -> String {
|
||||
format!("{}_to_{value_name}", Self::to_string().to_lowercase())
|
||||
}
|
||||
fn path(path: &Path, value_name: &str) -> PathBuf {
|
||||
path.join(Self::to_folder_name(value_name))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> StoredIndex for I
|
||||
@@ -51,8 +61,12 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_string<'a>() -> &'a str {
|
||||
fn to_string() -> String {
|
||||
std::any::type_name::<I>()
|
||||
.split("::")
|
||||
.last()
|
||||
.unwrap()
|
||||
.to_lowercase()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -53,7 +53,12 @@ pub trait VecIterator<'a>: BaseVecIterator<Item = (Self::I, Value<'a, Self::T>)>
|
||||
|
||||
#[inline]
|
||||
fn unwrap_get_inner(&mut self, i: Self::I) -> Self::T {
|
||||
self.get_(i.unwrap_to_usize()).unwrap().into_inner()
|
||||
self.unwrap_get_inner_(i.unwrap_to_usize())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unwrap_get_inner_(&mut self, i: usize) -> Self::T {
|
||||
self.get_(i).unwrap().into_inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -74,7 +79,7 @@ pub trait VecIterator<'a>: BaseVecIterator<Item = (Self::I, Value<'a, Self::T>)>
|
||||
self.next().map(|(i, v)| (i, Value::Owned(v.into_inner())))
|
||||
}
|
||||
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
Self::I::to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +357,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{path::Path, time::Duration};
|
||||
use std::{fs, path::Path, time::Duration};
|
||||
|
||||
use brk_exit::Exit;
|
||||
use clap_derive::ValueEnum;
|
||||
@@ -84,7 +84,7 @@ where
|
||||
pub fn forced_import_or_init_from_1(
|
||||
mode: Computation,
|
||||
path: &Path,
|
||||
name: &str,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
source: BoxedAnyIterableVec<S1I, S1T>,
|
||||
@@ -92,11 +92,12 @@ where
|
||||
) -> Result<Self> {
|
||||
Ok(match mode {
|
||||
Computation::Eager => Self::Eager {
|
||||
vec: EagerVec::forced_import(path, version, compressed)?,
|
||||
vec: EagerVec::forced_import(path, value_name, version, compressed)?,
|
||||
deps: Dependencies::From1(source, compute),
|
||||
},
|
||||
Computation::Lazy => {
|
||||
Self::LazyFrom1(LazyVecFrom1::init(name, version, source, compute))
|
||||
let _ = fs::remove_dir_all(I::path(path, value_name));
|
||||
Self::LazyFrom1(LazyVecFrom1::init(value_name, version, source, compute))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -105,7 +106,7 @@ where
|
||||
pub fn forced_import_or_init_from_2(
|
||||
mode: Computation,
|
||||
path: &Path,
|
||||
name: &str,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
source1: BoxedAnyIterableVec<S1I, S1T>,
|
||||
@@ -114,11 +115,14 @@ where
|
||||
) -> Result<Self> {
|
||||
Ok(match mode {
|
||||
Computation::Eager => Self::Eager {
|
||||
vec: EagerVec::forced_import(path, version, compressed)?,
|
||||
vec: EagerVec::forced_import(path, value_name, version, compressed)?,
|
||||
deps: Dependencies::From2((source1, source2), compute),
|
||||
},
|
||||
Computation::Lazy => {
|
||||
Self::LazyFrom2(LazyVecFrom2::init(name, version, source1, source2, compute))
|
||||
let _ = fs::remove_dir_all(I::path(path, value_name));
|
||||
Self::LazyFrom2(LazyVecFrom2::init(
|
||||
value_name, version, source1, source2, compute,
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -127,7 +131,7 @@ where
|
||||
pub fn forced_import_or_init_from_3(
|
||||
mode: Computation,
|
||||
path: &Path,
|
||||
name: &str,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
source1: BoxedAnyIterableVec<S1I, S1T>,
|
||||
@@ -137,12 +141,15 @@ where
|
||||
) -> Result<Self> {
|
||||
Ok(match mode {
|
||||
Computation::Eager => Self::Eager {
|
||||
vec: EagerVec::forced_import(path, version, compressed)?,
|
||||
vec: EagerVec::forced_import(path, value_name, version, compressed)?,
|
||||
deps: Dependencies::From3((source1, source2, source3), compute),
|
||||
},
|
||||
Computation::Lazy => Self::LazyFrom3(LazyVecFrom3::init(
|
||||
name, version, source1, source2, source3, compute,
|
||||
)),
|
||||
Computation::Lazy => {
|
||||
let _ = fs::remove_dir_all(I::path(path, value_name));
|
||||
Self::LazyFrom3(LazyVecFrom3::init(
|
||||
value_name, version, source1, source2, source3, compute,
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -220,7 +227,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
use core::error;
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
f32,
|
||||
fmt::Debug,
|
||||
ops::Add,
|
||||
ops::{Add, Div, Mul},
|
||||
path::{Path, PathBuf},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use brk_core::{Bitcoin, CheckedSub, Close, Dollars, Height, Sats, StoredUsize, TxIndex};
|
||||
use arc_swap::ArcSwap;
|
||||
use brk_core::{
|
||||
Bitcoin, CheckedSub, Close, Date, DateIndex, Dollars, Height, Sats, StoredUsize, TxIndex,
|
||||
};
|
||||
use brk_exit::Exit;
|
||||
use log::info;
|
||||
use memmap2::Mmap;
|
||||
|
||||
use crate::{
|
||||
AnyCollectableVec, AnyIterableVec, AnyVec, BoxedVecIterator, CollectableVec, Compressed, Error,
|
||||
@@ -20,6 +25,7 @@ use crate::{
|
||||
const ONE_KIB: usize = 1024;
|
||||
const ONE_MIB: usize = ONE_KIB * ONE_KIB;
|
||||
const MAX_CACHE_SIZE: usize = 210 * ONE_MIB;
|
||||
const DCA_AMOUNT: Dollars = Dollars::mint(100.0);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EagerVec<I, T> {
|
||||
@@ -34,8 +40,13 @@ where
|
||||
{
|
||||
const SIZE_OF: usize = size_of::<T>();
|
||||
|
||||
pub fn forced_import(path: &Path, version: Version, compressed: Compressed) -> Result<Self> {
|
||||
let inner = StoredVec::forced_import(path, version, compressed)?;
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
) -> Result<Self> {
|
||||
let inner = StoredVec::forced_import(path, value_name, version, compressed)?;
|
||||
|
||||
Ok(Self {
|
||||
computed_version: None,
|
||||
@@ -88,6 +99,18 @@ where
|
||||
self.inner.path()
|
||||
}
|
||||
|
||||
pub fn get_or_read(&self, index: I, mmap: &Mmap) -> Result<Option<Value<T>>> {
|
||||
self.inner.get_or_read(index, mmap)
|
||||
}
|
||||
|
||||
pub fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
self.inner.mmap()
|
||||
}
|
||||
|
||||
pub fn inner_version(&self) -> Version {
|
||||
self.inner.version()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn path_computed_version(&self) -> PathBuf {
|
||||
self.inner.path().join("computed_version")
|
||||
@@ -171,6 +194,90 @@ where
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_divide<T2, T3, T4>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
divided: &impl AnyIterableVec<I, T2>,
|
||||
divider: &impl AnyIterableVec<I, T3>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T2: StoredType + Div<T3, Output = T4>,
|
||||
T3: StoredType,
|
||||
T4: Mul<usize, Output = T4> + CheckedSub<usize>,
|
||||
T: From<T4>,
|
||||
{
|
||||
self.compute_divide_(max_from, divided, divider, exit, false, false)
|
||||
}
|
||||
|
||||
pub fn compute_percentage<T2, T3, T4>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
divided: &impl AnyIterableVec<I, T2>,
|
||||
divider: &impl AnyIterableVec<I, T3>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T2: StoredType + Div<T3, Output = T4>,
|
||||
T3: StoredType,
|
||||
T4: Mul<usize, Output = T4> + CheckedSub<usize>,
|
||||
T: From<T4>,
|
||||
{
|
||||
self.compute_divide_(max_from, divided, divider, exit, true, false)
|
||||
}
|
||||
|
||||
pub fn compute_percentage_difference<T2, T3, T4>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
divided: &impl AnyIterableVec<I, T2>,
|
||||
divider: &impl AnyIterableVec<I, T3>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T2: StoredType + Div<T3, Output = T4>,
|
||||
T3: StoredType,
|
||||
T4: Mul<usize, Output = T4> + CheckedSub<usize>,
|
||||
T: From<T4>,
|
||||
{
|
||||
self.compute_divide_(max_from, divided, divider, exit, true, true)
|
||||
}
|
||||
|
||||
pub fn compute_divide_<T2, T3, T4>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
divided: &impl AnyIterableVec<I, T2>,
|
||||
divider: &impl AnyIterableVec<I, T3>,
|
||||
exit: &Exit,
|
||||
as_percentage: bool,
|
||||
as_difference: bool,
|
||||
) -> Result<()>
|
||||
where
|
||||
T2: StoredType + Div<T3, Output = T4>,
|
||||
T3: StoredType,
|
||||
T4: Mul<usize, Output = T4> + CheckedSub<usize>,
|
||||
T: From<T4>,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + divided.version() + divider.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
let multiplier = if as_percentage { 100 } else { 1 };
|
||||
let subtract = if as_difference { multiplier } else { 0 };
|
||||
|
||||
let mut divider_iter = divider.iter();
|
||||
divided.iter_at(index).try_for_each(|(i, divided)| {
|
||||
let divided = divided.into_inner();
|
||||
let divider = divider_iter.unwrap_get_inner(i);
|
||||
let v = (divided / divider * multiplier)
|
||||
.checked_sub(subtract)
|
||||
.unwrap();
|
||||
self.forced_push_at(i, T::from(v), exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_inverse_more_to_less(
|
||||
&mut self,
|
||||
max_from: T,
|
||||
@@ -406,6 +513,326 @@ where
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_sma<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl AnyIterableVec<I, T2>,
|
||||
sma: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: Add<T, Output = T> + From<T2> + Div<usize, Output = T> + From<f32>,
|
||||
T2: StoredType,
|
||||
f32: From<T> + From<T2>,
|
||||
{
|
||||
self.compute_sma_(max_from, source, sma, exit, None)
|
||||
}
|
||||
|
||||
pub fn compute_sma_<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl AnyIterableVec<I, T2>,
|
||||
sma: usize,
|
||||
exit: &Exit,
|
||||
min_i: Option<I>,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: Add<T, Output = T> + From<T2> + Div<usize, Output = T> + From<f32>,
|
||||
T2: StoredType,
|
||||
f32: From<T> + From<T2>,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + source.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
let mut prev = None;
|
||||
let min_prev_i = min_i.unwrap_or_default().unwrap_to_usize();
|
||||
source.iter_at(index).try_for_each(|(i, value)| {
|
||||
let value = value.into_inner();
|
||||
|
||||
if min_i.is_none() || min_i.is_some_and(|min_i| min_i <= i) {
|
||||
if prev.is_none() {
|
||||
let i = i.unwrap_to_usize();
|
||||
prev.replace(if i > min_prev_i {
|
||||
self.into_iter().unwrap_get_inner_(i - 1)
|
||||
} else {
|
||||
T::from(0.0)
|
||||
});
|
||||
}
|
||||
let len = (i.unwrap_to_usize() - min_prev_i + 1).min(sma);
|
||||
let sma = T::from(
|
||||
(f32::from(prev.clone().unwrap()) * (len - 1) as f32 + f32::from(value))
|
||||
/ len as f32,
|
||||
);
|
||||
|
||||
prev.replace(sma.clone());
|
||||
self.forced_push_at(i, sma, exit)
|
||||
} else {
|
||||
self.forced_push_at(i, T::from(f32::NAN), exit)
|
||||
}
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_previous_value<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl AnyIterableVec<I, T2>,
|
||||
len: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
I: CheckedSub,
|
||||
T2: StoredType + Default,
|
||||
f32: From<T2>,
|
||||
T: From<f32>,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + source.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
let mut source_iter = source.iter();
|
||||
(index.to_usize()?..source.len()).try_for_each(|i| {
|
||||
let i = I::from(i);
|
||||
|
||||
let previous_value = i
|
||||
.checked_sub(I::from(len))
|
||||
.map(|prev_i| f32::from(source_iter.unwrap_get_inner(prev_i)))
|
||||
.unwrap_or(f32::NAN);
|
||||
|
||||
self.forced_push_at(i, T::from(previous_value), exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_percentage_change<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl AnyIterableVec<I, T2>,
|
||||
len: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
I: CheckedSub,
|
||||
T2: StoredType + Default,
|
||||
f32: From<T2>,
|
||||
T: From<f32>,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + source.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
let mut source_iter = source.iter();
|
||||
source.iter_at(index).try_for_each(|(i, b)| {
|
||||
let previous_value = f32::from(
|
||||
i.checked_sub(I::from(len))
|
||||
.map(|prev_i| source_iter.unwrap_get_inner(prev_i))
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
|
||||
let last_value = f32::from(b.into_inner());
|
||||
|
||||
let percentage_change = ((last_value / previous_value) - 1.0) * 100.0;
|
||||
|
||||
self.forced_push_at(i, T::from(percentage_change), exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_cagr<T2>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
percentage_returns: &impl AnyIterableVec<I, T2>,
|
||||
days: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
I: CheckedSub,
|
||||
T2: StoredType + Default,
|
||||
f32: From<T2>,
|
||||
T: From<f32>,
|
||||
{
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + percentage_returns.version(),
|
||||
)?;
|
||||
|
||||
if days % 365 != 0 {
|
||||
panic!("bad days");
|
||||
}
|
||||
|
||||
let years = days / 365;
|
||||
let index = max_from.min(I::from(self.len()));
|
||||
percentage_returns
|
||||
.iter_at(index)
|
||||
.try_for_each(|(i, percentage)| {
|
||||
let percentage = percentage.into_inner();
|
||||
|
||||
let cagr = (((f32::from(percentage) / 100.0 + 1.0).powf(1.0 / years as f32)) - 1.0)
|
||||
* 100.0;
|
||||
|
||||
self.forced_push_at(i, T::from(cagr), exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl EagerVec<DateIndex, Sats> {
|
||||
pub fn compute_dca_stack_via_len(
|
||||
&mut self,
|
||||
max_from: DateIndex,
|
||||
closes: &impl AnyIterableVec<DateIndex, Close<Dollars>>,
|
||||
len: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + closes.version(),
|
||||
)?;
|
||||
|
||||
let mut other_iter = closes.iter();
|
||||
let mut prev = None;
|
||||
|
||||
let index = max_from.min(DateIndex::from(self.len()));
|
||||
closes.iter_at(index).try_for_each(|(i, closes)| {
|
||||
let price = *closes.into_inner();
|
||||
let i_usize = i.unwrap_to_usize();
|
||||
if prev.is_none() {
|
||||
if i_usize == 0 {
|
||||
prev.replace(Sats::ZERO);
|
||||
} else {
|
||||
prev.replace(self.into_iter().unwrap_get_inner_(i_usize - 1));
|
||||
}
|
||||
}
|
||||
|
||||
let mut stack = Sats::ZERO;
|
||||
|
||||
if price != Dollars::ZERO {
|
||||
stack = prev.unwrap() + Sats::from(Bitcoin::from(DCA_AMOUNT / price));
|
||||
|
||||
if i_usize >= len {
|
||||
let prev_price = *other_iter.unwrap_get_inner_(i_usize - len);
|
||||
if prev_price != Dollars::ZERO {
|
||||
stack = stack
|
||||
.checked_sub(Sats::from(Bitcoin::from(DCA_AMOUNT / prev_price)))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev.replace(stack);
|
||||
|
||||
self.forced_push_at(i, stack, exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_dca_stack_via_from(
|
||||
&mut self,
|
||||
max_from: DateIndex,
|
||||
closes: &impl AnyIterableVec<DateIndex, Close<Dollars>>,
|
||||
from: DateIndex,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + closes.version(),
|
||||
)?;
|
||||
|
||||
let mut prev = None;
|
||||
|
||||
let index = max_from.min(DateIndex::from(self.len()));
|
||||
closes.iter_at(index).try_for_each(|(i, closes)| {
|
||||
let price = *closes.into_inner();
|
||||
let i_usize = i.unwrap_to_usize();
|
||||
if prev.is_none() {
|
||||
if i_usize == 0 {
|
||||
prev.replace(Sats::ZERO);
|
||||
} else {
|
||||
prev.replace(self.into_iter().unwrap_get_inner_(i_usize - 1));
|
||||
}
|
||||
}
|
||||
|
||||
let mut stack = Sats::ZERO;
|
||||
|
||||
if price != Dollars::ZERO && i >= from {
|
||||
stack = prev.unwrap() + Sats::from(Bitcoin::from(DCA_AMOUNT / price));
|
||||
}
|
||||
|
||||
prev.replace(stack);
|
||||
|
||||
self.forced_push_at(i, stack, exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl EagerVec<DateIndex, Dollars> {
|
||||
pub fn compute_dca_avg_price_via_len(
|
||||
&mut self,
|
||||
max_from: DateIndex,
|
||||
stacks: &impl AnyIterableVec<DateIndex, Sats>,
|
||||
len: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::TWO + self.inner.version() + stacks.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(DateIndex::from(self.len()));
|
||||
|
||||
let first_price_date = DateIndex::try_from(Date::new(2010, 8, 16)).unwrap();
|
||||
|
||||
stacks.iter_at(index).try_for_each(|(i, stack)| {
|
||||
let stack = stack.into_inner();
|
||||
let mut avg_price = Dollars::from(f64::NAN);
|
||||
if i > first_price_date {
|
||||
avg_price = DCA_AMOUNT
|
||||
* len
|
||||
.min(i.unwrap_to_usize() + 1)
|
||||
.min(i.checked_sub(first_price_date).unwrap().unwrap_to_usize() + 1)
|
||||
/ Bitcoin::from(stack);
|
||||
}
|
||||
self.forced_push_at(i, avg_price, exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_dca_avg_price_via_from(
|
||||
&mut self,
|
||||
max_from: DateIndex,
|
||||
stacks: &impl AnyIterableVec<DateIndex, Sats>,
|
||||
from: DateIndex,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.validate_computed_version_or_reset_file(
|
||||
Version::ZERO + self.inner.version() + stacks.version(),
|
||||
)?;
|
||||
|
||||
let index = max_from.min(DateIndex::from(self.len()));
|
||||
|
||||
let from_usize = from.unwrap_to_usize();
|
||||
|
||||
stacks.iter_at(index).try_for_each(|(i, stack)| {
|
||||
let stack = stack.into_inner();
|
||||
let mut avg_price = Dollars::from(f64::NAN);
|
||||
if i >= from {
|
||||
avg_price =
|
||||
DCA_AMOUNT * (i.unwrap_to_usize() + 1 - from_usize) / Bitcoin::from(stack);
|
||||
}
|
||||
self.forced_push_at(i, avg_price, exit)
|
||||
})?;
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> EagerVec<I, Bitcoin>
|
||||
@@ -527,7 +954,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,17 @@ where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
pub fn forced_import(path: &Path, version: Version, compressed: Compressed) -> Result<Self> {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
) -> Result<Self> {
|
||||
let inner = StoredVec::forced_import(path, value_name, version, compressed)?;
|
||||
|
||||
Ok(Self {
|
||||
height: Height::try_from(Self::path_height_(path).as_path()).ok(),
|
||||
inner: StoredVec::forced_import(path, version, compressed)?,
|
||||
height: Height::try_from(Self::path_height_(inner.path()).as_path()).ok(),
|
||||
inner,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -117,7 +124,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ where
|
||||
S1T: StoredType,
|
||||
{
|
||||
pub fn init(
|
||||
name: &str,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
source: BoxedAnyIterableVec<S1I, S1T>,
|
||||
compute: ComputeFrom1<I, T, S1I, S1T>,
|
||||
@@ -36,7 +36,7 @@ where
|
||||
}
|
||||
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
name: I::to_folder_name(value_name),
|
||||
version,
|
||||
source,
|
||||
compute,
|
||||
@@ -129,7 +129,7 @@ where
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ where
|
||||
S2T: StoredType,
|
||||
{
|
||||
pub fn init(
|
||||
name: &str,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
source1: BoxedAnyIterableVec<S1I, S1T>,
|
||||
source2: BoxedAnyIterableVec<S2I, S2T>,
|
||||
@@ -50,7 +50,7 @@ where
|
||||
}
|
||||
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
name: I::to_folder_name(value_name),
|
||||
version,
|
||||
source1,
|
||||
source2,
|
||||
@@ -163,7 +163,7 @@ where
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ where
|
||||
S3T: StoredType,
|
||||
{
|
||||
pub fn init(
|
||||
name: &str,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
source1: BoxedAnyIterableVec<S1I, S1T>,
|
||||
source2: BoxedAnyIterableVec<S2I, S2T>,
|
||||
@@ -56,7 +56,7 @@ where
|
||||
}
|
||||
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
name: I::to_folder_name(value_name),
|
||||
version,
|
||||
source1,
|
||||
source2,
|
||||
@@ -192,7 +192,7 @@ where
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,19 @@ where
|
||||
I: StoredIndex,
|
||||
T: StoredType,
|
||||
{
|
||||
pub fn forced_import(path: &Path, version: Version, compressed: Compressed) -> Result<Self> {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
value_name: &str,
|
||||
version: Version,
|
||||
compressed: Compressed,
|
||||
) -> Result<Self> {
|
||||
let path = I::path(path, value_name);
|
||||
if *compressed {
|
||||
Ok(Self::Compressed(CompressedVec::forced_import(
|
||||
path, version,
|
||||
&path, version,
|
||||
)?))
|
||||
} else {
|
||||
Ok(Self::Raw(RawVec::forced_import(path, version)?))
|
||||
Ok(Self::Raw(RawVec::forced_import(&path, version)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +119,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_type_to_string(&self) -> &str {
|
||||
fn index_type_to_string(&self) -> String {
|
||||
I::to_string()
|
||||
}
|
||||
|
||||
|
||||
@@ -441,9 +441,9 @@
|
||||
h1,
|
||||
h2 {
|
||||
text-transform: uppercase;
|
||||
font-size: var(--font-size-2xl);
|
||||
line-height: var(--line-height-2xl);
|
||||
font-weight: 300;
|
||||
font-size: var(--font-size-xl);
|
||||
line-height: var(--line-height-xl);
|
||||
font-weight: 350;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@@ -990,16 +990,17 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
margin-left: var(--negative-main-padding);
|
||||
margin-right: var(--negative-main-padding);
|
||||
padding-left: var(--main-padding);
|
||||
padding-right: var(--main-padding);
|
||||
padding-bottom: 1rem;
|
||||
margin: -0.5rem var(--negative-main-padding);
|
||||
padding: 1rem var(--main-padding);
|
||||
overflow-x: auto;
|
||||
min-width: 0;
|
||||
font-size: var(--font-size-sm);
|
||||
line-height: var(--line-height-sm);
|
||||
height: 2rem;
|
||||
scrollbar-width: thin;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> div {
|
||||
flex: 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
|
||||
/** @import {IChartApi, ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData, SeriesType, IPaneApi, LineSeriesOptions} from './v5.0.6-treeshaked/types' */
|
||||
/** @import {IChartApi, ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData, SeriesType, IPaneApi, BaselineStyleOptions} from './v5.0.6-treeshaked/types' */
|
||||
|
||||
/**
|
||||
* @typedef {[number, number, number, number]} OHLCTuple
|
||||
@@ -50,7 +50,6 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
autoSize: true,
|
||||
layout: {
|
||||
fontFamily: elements.style.fontFamily,
|
||||
// fontSize: 13,
|
||||
background: { color: "transparent" },
|
||||
attributionLogo: false,
|
||||
colorSpace: "display-p3",
|
||||
@@ -71,17 +70,13 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
const chart = lc.createChart(element, options);
|
||||
|
||||
chart.priceScale("right").applyOptions({
|
||||
// scaleMargins: {
|
||||
// top: 0.15,
|
||||
// bottom: 0.05,
|
||||
// },
|
||||
minimumWidth: 80,
|
||||
});
|
||||
|
||||
signals.createEffect(
|
||||
() => ({
|
||||
defaultColor: colors.default(),
|
||||
offColor: colors.off(),
|
||||
offColor: colors.gray(),
|
||||
borderColor: colors.border(),
|
||||
}),
|
||||
({ defaultColor, offColor, borderColor }) => {
|
||||
@@ -161,16 +156,24 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
div.classList.add("chart");
|
||||
parent.append(div);
|
||||
|
||||
const legend = createLegend({
|
||||
const legendTop = createLegend({
|
||||
parent: div,
|
||||
utils,
|
||||
signals,
|
||||
paneIndex: 0,
|
||||
});
|
||||
|
||||
const chartDiv = window.document.createElement("div");
|
||||
chartDiv.classList.add("lightweight-chart");
|
||||
div.append(chartDiv);
|
||||
|
||||
const legendBottom = createLegend({
|
||||
parent: div,
|
||||
utils,
|
||||
signals,
|
||||
paneIndex: 1,
|
||||
});
|
||||
|
||||
let ichart = /** @type {IChartApi | null} */ (null);
|
||||
let timeScaleSet = false;
|
||||
|
||||
@@ -220,7 +223,12 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
offset += 1;
|
||||
}
|
||||
const v = ohlcs[i];
|
||||
if (typeof v === "number") {
|
||||
if (v === null) {
|
||||
data[i - offset] = {
|
||||
time,
|
||||
value: NaN,
|
||||
};
|
||||
} else if (typeof v === "number") {
|
||||
data[i - offset] = {
|
||||
time,
|
||||
value: v,
|
||||
@@ -363,7 +371,7 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
);
|
||||
}
|
||||
|
||||
legend.add({
|
||||
(paneIndex ? legendBottom : legendTop).add({
|
||||
series,
|
||||
name,
|
||||
defaultActive,
|
||||
@@ -396,7 +404,7 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
* @param {Color} [args.color]
|
||||
* @param {number} [args.paneIndex]
|
||||
* @param {boolean} [args.defaultActive]
|
||||
* @param {DeepPartial<LineStyleOptions & SeriesOptionsCommon>} [args.options]
|
||||
* @param {DeepPartial<LineStyleOptions & SeriesOptionsCommon & CreatePriceLineOptions>} [args.options]
|
||||
*/
|
||||
addLineSeries({
|
||||
vecId,
|
||||
@@ -412,7 +420,7 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
|
||||
const paneIndex = _paneIndex ?? 0;
|
||||
|
||||
color ||= unit === "USD" ? colors.dollars : colors.bitcoin;
|
||||
color ||= unit === "USD" ? colors.green : colors.orange;
|
||||
|
||||
const series = ichart.addSeries(
|
||||
/** @type {SeriesDefinition<'Line'>} */ (lc.LineSeries),
|
||||
@@ -426,6 +434,11 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
paneIndex,
|
||||
);
|
||||
|
||||
const priceLineOptions = options?.createPriceLine;
|
||||
if (priceLineOptions) {
|
||||
createPriceLine(series, priceLineOptions, colors);
|
||||
}
|
||||
|
||||
let url = /** @type {string | undefined} */ (undefined);
|
||||
|
||||
if (vecId) {
|
||||
@@ -445,7 +458,7 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
);
|
||||
}
|
||||
|
||||
legend.add({
|
||||
(paneIndex ? legendBottom : legendTop).add({
|
||||
series,
|
||||
colors: [color],
|
||||
name,
|
||||
@@ -477,6 +490,7 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
* @param {VecId} [args.vecId]
|
||||
* @param {number} [args.paneIndex]
|
||||
* @param {boolean} [args.defaultActive]
|
||||
* @param {DeepPartial<BaselineStyleOptions & SeriesOptionsCommon & CreatePriceLineOptions>} [args.options]
|
||||
*/
|
||||
addBaselineSeries({
|
||||
vecId,
|
||||
@@ -485,29 +499,40 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
paneIndex: _paneIndex,
|
||||
defaultActive,
|
||||
data,
|
||||
options,
|
||||
}) {
|
||||
if (!ichart || !timeResource) throw Error("Chart not fully set");
|
||||
|
||||
const paneIndex = _paneIndex ?? 0;
|
||||
|
||||
console.log("OPTIONS", options);
|
||||
|
||||
const series = ichart.addSeries(
|
||||
/** @type {SeriesDefinition<'Baseline'>} */ (lc.BaselineSeries),
|
||||
{
|
||||
lineWidth: /** @type {any} */ (1.5),
|
||||
visible: defaultActive !== false,
|
||||
topLineColor: colors.green(),
|
||||
bottomLineColor: colors.red(),
|
||||
baseValue: {
|
||||
price: 0,
|
||||
},
|
||||
baseLineStyle: 0,
|
||||
baseLineWidth: 1,
|
||||
baseLineVisible: true,
|
||||
...options,
|
||||
topLineColor: options?.topLineColor ?? colors.green(),
|
||||
bottomLineColor: options?.bottomLineColor ?? colors.red(),
|
||||
priceLineVisible: false,
|
||||
bottomFillColor1: "transparent",
|
||||
bottomFillColor2: "transparent",
|
||||
topFillColor1: "transparent",
|
||||
topFillColor2: "transparent",
|
||||
lineVisible: true,
|
||||
},
|
||||
paneIndex,
|
||||
);
|
||||
|
||||
const priceLineOptions = options?.createPriceLine;
|
||||
if (priceLineOptions) {
|
||||
createPriceLine(series, priceLineOptions, colors);
|
||||
}
|
||||
|
||||
let url = /** @type {string | undefined} */ (undefined);
|
||||
|
||||
if (vecId) {
|
||||
@@ -528,9 +553,12 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
);
|
||||
}
|
||||
|
||||
legend.add({
|
||||
(paneIndex ? legendBottom : legendTop).add({
|
||||
series,
|
||||
colors: [colors.green, colors.red],
|
||||
colors: [
|
||||
() => options?.topLineColor ?? colors.green(),
|
||||
() => options?.bottomLineColor ?? colors.red(),
|
||||
],
|
||||
name,
|
||||
defaultActive,
|
||||
url,
|
||||
@@ -647,7 +675,8 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
ichart = null;
|
||||
timeScaleSet = false;
|
||||
activeResources.length = 0;
|
||||
legend.reset();
|
||||
legendTop.reset();
|
||||
legendBottom.reset();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -697,9 +726,10 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
|
||||
* @param {Object} args
|
||||
* @param {Element} args.parent
|
||||
* @param {Signals} args.signals
|
||||
* @param {number} args.paneIndex
|
||||
* @param {Utilities} args.utils
|
||||
*/
|
||||
function createLegend({ parent, signals, utils }) {
|
||||
function createLegend({ parent, signals, utils, paneIndex }) {
|
||||
const legendElement = window.document.createElement("legend");
|
||||
parent.append(legendElement);
|
||||
|
||||
@@ -721,7 +751,7 @@ function createLegend({ parent, signals, utils }) {
|
||||
|
||||
legendElement.append(div);
|
||||
|
||||
const nameId = utils.stringToId(name);
|
||||
const nameId = `${utils.stringToId(name)}-${paneIndex}`;
|
||||
|
||||
const active = signals.createSignal(defaultActive ?? true, {
|
||||
save: {
|
||||
@@ -998,3 +1028,18 @@ function createPaneHeightObserver({ ichart, paneIndex, signals, utils }) {
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ISeriesApi<SeriesType>} series
|
||||
* @param {DeepPartial<CreatePriceLine>} options
|
||||
* @param {Colors} colors
|
||||
*/
|
||||
function createPriceLine(series, options, colors) {
|
||||
series.createPriceLine({
|
||||
price: options.value || 0,
|
||||
color: colors.gray(),
|
||||
axisLabelVisible: false,
|
||||
lineWidth: 1,
|
||||
lineStyle: 4,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -229,14 +229,38 @@ export function init({
|
||||
vecIdToIndexes[blueprint.key]
|
||||
);
|
||||
if (indexes.includes(index)) {
|
||||
chart.addLineSeries({
|
||||
vecId: blueprint.key,
|
||||
color: blueprint.color,
|
||||
name: blueprint.title,
|
||||
unit,
|
||||
defaultActive: blueprint.defaultActive,
|
||||
paneIndex,
|
||||
});
|
||||
switch (blueprint.type) {
|
||||
case "Baseline": {
|
||||
chart.addBaselineSeries({
|
||||
vecId: blueprint.key,
|
||||
// color: blueprint.color,
|
||||
name: blueprint.title,
|
||||
unit,
|
||||
defaultActive: blueprint.defaultActive,
|
||||
paneIndex,
|
||||
options: {
|
||||
...blueprint.options,
|
||||
topLineColor: blueprint.colors?.[0](),
|
||||
bottomLineColor: blueprint.colors?.[1](),
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "Candlestick": {
|
||||
throw Error("TODO");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
chart.addLineSeries({
|
||||
vecId: blueprint.key,
|
||||
color: blueprint.color,
|
||||
name: blueprint.title,
|
||||
unit,
|
||||
defaultActive: blueprint.defaultActive,
|
||||
paneIndex,
|
||||
options: blueprint.options,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -246,8 +270,10 @@ export function init({
|
||||
?.timeScale()
|
||||
.subscribeVisibleLogicalRangeChange(
|
||||
utils.debounce((t) => {
|
||||
from.set(t.from);
|
||||
to.set(t.to);
|
||||
if (t) {
|
||||
from.set(t.from);
|
||||
to.set(t.to);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -267,7 +293,7 @@ export function init({
|
||||
*/
|
||||
function createIndexSelector({ elements, signals, utils }) {
|
||||
const { field, selected } = utils.dom.createHorizontalChoiceField({
|
||||
title: "Index",
|
||||
// title: "Index",
|
||||
defaultValue: "date",
|
||||
keyPrefix: "charts",
|
||||
key: "index",
|
||||
|
||||
+203
-127
@@ -1,10 +1,10 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, ChartableIndex } from "./options"
|
||||
* @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, ChartableIndex,CreatePriceLineOptions, CreatePriceLine } from "./options"
|
||||
* @import {Valued, SingleValueData, CandlestickData, ChartData, OHLCTuple} from "../packages/lightweight-charts/wrapper"
|
||||
* @import * as _ from "../packages/ufuzzy/v1.0.14/types"
|
||||
* @import { createChart as CreateClassicChart, LineStyleOptions, DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior, WhitespaceData, ISeriesApi, Time, LineData, LogicalRange, SeriesType, BaselineStyleOptions, SeriesOptionsCommon, BaselineData, CandlestickStyleOptions } from "../packages/lightweight-charts/v5.0.6-treeshaked/types"
|
||||
* @import { createChart as CreateClassicChart, LineStyleOptions, DeepPartial, ChartOptions, IChartApi, IHorzScaleBehavior, WhitespaceData, ISeriesApi, Time, LineData, LogicalRange, BaselineStyleOptions, SeriesOptionsCommon, BaselineData, CandlestickStyleOptions } from "../packages/lightweight-charts/v5.0.6-treeshaked/types"
|
||||
* @import { SignalOptions } from "../packages/solid-signals/v0.3.0-treeshaked/types/core/core"
|
||||
* @import {Signal, Signals} from "../packages/solid-signals/types";
|
||||
* @import { getOwner as GetOwner, onCleanup as OnCleanup, Owner } from "../packages/solid-signals/v0.3.0-treeshaked/types/core/owner"
|
||||
@@ -25,7 +25,7 @@
|
||||
* "Hash" |
|
||||
* "Index" |
|
||||
* "mb" |
|
||||
* "%" |
|
||||
* "percentage" |
|
||||
* "Ratio" |
|
||||
* "Sats" |
|
||||
* "Seconds" |
|
||||
@@ -37,9 +37,15 @@
|
||||
* "Version" |
|
||||
* "WU" |
|
||||
* "Bool" |
|
||||
* "Days" |
|
||||
* "Years" |
|
||||
* "Locktime" |
|
||||
* "sat/vB" |
|
||||
* "vB"
|
||||
* "constant" |
|
||||
* "cagr" |
|
||||
* "vB" |
|
||||
* "performance" |
|
||||
* "zscore"
|
||||
* } Unit
|
||||
*/
|
||||
|
||||
@@ -682,10 +688,22 @@ function createUtils() {
|
||||
function vecidToUnit(id) {
|
||||
/** @type {Unit} */
|
||||
let unit;
|
||||
if (id.includes("index") || id.includes("height") || id.includes("epoch")) {
|
||||
unit = "Index";
|
||||
if (id.endsWith("zscore")) {
|
||||
unit = "zscore";
|
||||
} else if (id.endsWith("cagr")) {
|
||||
unit = "cagr";
|
||||
} else if (id.endsWith("returns")) {
|
||||
unit = "performance";
|
||||
} else if (id === "drawdown" || id.endsWith("oscillator")) {
|
||||
unit = "percentage";
|
||||
} else if (id.endsWith("-as-price")) {
|
||||
unit = "USD";
|
||||
} else if (id.includes("type")) {
|
||||
unit = "Type";
|
||||
} else if (id.includes("days-")) {
|
||||
unit = "Days";
|
||||
} else if (id.includes("years-")) {
|
||||
unit = "Years";
|
||||
} else if (id === "rawlocktime") {
|
||||
unit = "Locktime";
|
||||
} else if (id.startsWith("is-")) {
|
||||
@@ -705,6 +723,8 @@ function createUtils() {
|
||||
unit = "Cents";
|
||||
} else if (id.includes("in-usd")) {
|
||||
unit = "USD";
|
||||
} else if (id.includes("ratio")) {
|
||||
unit = "Ratio";
|
||||
} else if (id.includes("in-btc")) {
|
||||
unit = "BTC";
|
||||
} else if (
|
||||
@@ -714,7 +734,11 @@ function createUtils() {
|
||||
id.includes("output-value") ||
|
||||
id.includes("fee") ||
|
||||
id.includes("coinbase") ||
|
||||
id.includes("subsidy")
|
||||
id.includes("subsidy") ||
|
||||
id.endsWith("stack") ||
|
||||
id.includes("supply") ||
|
||||
id.includes("rewards") ||
|
||||
id.includes("realized-cap")
|
||||
) {
|
||||
unit = "Sats";
|
||||
} else if (
|
||||
@@ -722,7 +746,13 @@ function createUtils() {
|
||||
id.includes("high") ||
|
||||
id.includes("low") ||
|
||||
id.includes("close") ||
|
||||
id.includes("ohlc")
|
||||
id.includes("ohlc") ||
|
||||
id.includes("marketcap") ||
|
||||
id.includes("ath") ||
|
||||
id.includes("-sma") ||
|
||||
id.endsWith("-price") ||
|
||||
id.startsWith("price-") ||
|
||||
id.startsWith("realized-")
|
||||
) {
|
||||
unit = "USD";
|
||||
} else if (id.includes("count") || id.match(/v[1-3]/g)) {
|
||||
@@ -731,6 +761,14 @@ function createUtils() {
|
||||
unit = "Date";
|
||||
} else if (id.includes("timestamp")) {
|
||||
unit = "Timestamp";
|
||||
} else if (
|
||||
id.includes("index") ||
|
||||
id.includes("height") ||
|
||||
id.includes("epoch")
|
||||
) {
|
||||
unit = "Index";
|
||||
} else if (id === "0" || id === "1" || id === "50" || id === "100") {
|
||||
unit = "constant";
|
||||
} else if (id.includes("difficulty")) {
|
||||
unit = "Difficulty";
|
||||
} else if (id.includes("-size")) {
|
||||
@@ -766,6 +804,8 @@ function createUtils() {
|
||||
return numberToUSFormat(value, 1);
|
||||
} else if (absoluteValue < 100_000) {
|
||||
return numberToUSFormat(value, 0);
|
||||
} else if (absoluteValue < 200_000) {
|
||||
return `${numberToUSFormat(value / 1_000, 2)}K`;
|
||||
} else if (absoluteValue < 1_000_000) {
|
||||
return `${numberToUSFormat(value / 1_000, 1)}K`;
|
||||
} else if (absoluteValue >= 900_000_000_000_000_000) {
|
||||
@@ -1072,7 +1112,13 @@ function createUtils() {
|
||||
* @param {string} s
|
||||
*/
|
||||
function stringToId(s) {
|
||||
return s.replace(/\W/g, " ").trim().replace(/ +/g, "-").toLowerCase();
|
||||
return (
|
||||
s
|
||||
// .replace(/\W/g, " ")
|
||||
.trim()
|
||||
.replace(/ +/g, "-")
|
||||
.toLowerCase()
|
||||
);
|
||||
}
|
||||
|
||||
const api = (() => {
|
||||
@@ -1533,7 +1579,7 @@ function createColors(dark, elements) {
|
||||
function rose() {
|
||||
return getColor("rose");
|
||||
}
|
||||
function off() {
|
||||
function gray() {
|
||||
return getColor("gray");
|
||||
}
|
||||
|
||||
@@ -1555,134 +1601,164 @@ function createColors(dark, elements) {
|
||||
|
||||
return {
|
||||
default: textColor,
|
||||
off,
|
||||
gray,
|
||||
border: borderColor,
|
||||
lightBitcoin: yellow,
|
||||
bitcoin: orange,
|
||||
offBitcoin: red,
|
||||
lightDollars: lime,
|
||||
dollars: green,
|
||||
offDollars: emerald,
|
||||
// dollars: green,
|
||||
// offDollars: emerald,
|
||||
|
||||
yellow,
|
||||
lime,
|
||||
orange,
|
||||
red,
|
||||
orange,
|
||||
amber,
|
||||
yellow,
|
||||
avocado,
|
||||
lime,
|
||||
green,
|
||||
emerald,
|
||||
teal,
|
||||
cyan,
|
||||
sky,
|
||||
blue,
|
||||
rose,
|
||||
green,
|
||||
amber,
|
||||
avocado,
|
||||
cyan,
|
||||
indigo,
|
||||
violet,
|
||||
purple,
|
||||
fuchsia,
|
||||
pink,
|
||||
rose,
|
||||
|
||||
_1d: pink,
|
||||
_1w: red,
|
||||
_8d: orange,
|
||||
_13d: amber,
|
||||
_21d: yellow,
|
||||
_1m: lime,
|
||||
_34d: green,
|
||||
_55d: emerald,
|
||||
_89d: teal,
|
||||
_144d: cyan,
|
||||
_6m: sky,
|
||||
_1y: blue,
|
||||
_2y: indigo,
|
||||
_200w: violet,
|
||||
_4y: purple,
|
||||
_10y: fuchsia,
|
||||
// _1d: pink,
|
||||
// _1w: red,
|
||||
// _8d: orange,
|
||||
// _13d: amber,
|
||||
// _21d: yellow,
|
||||
// _1m: lime,
|
||||
// _34d: green,
|
||||
// _55d: emerald,
|
||||
// _89d: teal,
|
||||
// _144d: cyan,
|
||||
// _6m: sky,
|
||||
// _1y: blue,
|
||||
// _2y: indigo,
|
||||
// _200w: violet,
|
||||
// _4y: purple,
|
||||
// _10y: fuchsia,
|
||||
|
||||
p2pk: lime,
|
||||
p2pkh: violet,
|
||||
p2sh: emerald,
|
||||
p2wpkh: cyan,
|
||||
p2wsh: pink,
|
||||
p2tr: blue,
|
||||
crab: red,
|
||||
fish: lime,
|
||||
humpback: violet,
|
||||
plankton: emerald,
|
||||
shark: cyan,
|
||||
shrimp: pink,
|
||||
whale: blue,
|
||||
megalodon: purple,
|
||||
realizedPrice: orange,
|
||||
oneMonthHolders: cyan,
|
||||
threeMonthsHolders: lime,
|
||||
sth: yellow,
|
||||
sixMonthsHolder: red,
|
||||
oneYearHolders: pink,
|
||||
twoYearsHolders: purple,
|
||||
lth: fuchsia,
|
||||
balancedPrice: yellow,
|
||||
cointimePrice: yellow,
|
||||
trueMarketMeanPrice: blue,
|
||||
vaultedPrice: green,
|
||||
cvdd: lime,
|
||||
terminalPrice: red,
|
||||
loss: red,
|
||||
profit: green,
|
||||
thermoCap: green,
|
||||
investorCap: rose,
|
||||
realizedCap: orange,
|
||||
offLiveliness: red,
|
||||
liveliness: rose,
|
||||
vaultedness: green,
|
||||
activityToVaultednessRatio: violet,
|
||||
up_to_1d: pink,
|
||||
up_to_1w: red,
|
||||
up_to_1m: orange,
|
||||
up_to_2m: amber,
|
||||
up_to_3m: yellow,
|
||||
up_to_4m: lime,
|
||||
up_to_5m: green,
|
||||
up_to_6m: teal,
|
||||
up_to_1y: sky,
|
||||
up_to_2y: indigo,
|
||||
up_to_3y: violet,
|
||||
up_to_4y: purple,
|
||||
up_to_5y: red,
|
||||
up_to_7y: orange,
|
||||
up_to_10y: amber,
|
||||
up_to_15y: yellow,
|
||||
from_10y_to_15y: purple,
|
||||
from_7y_to_10y: violet,
|
||||
from_5y_to_7y: indigo,
|
||||
from_3y_to_5y: sky,
|
||||
from_2y_to_3y: teal,
|
||||
from_1y_to_2y: green,
|
||||
from_6m_to_1y: lime,
|
||||
from_3m_to_6m: yellow,
|
||||
from_1m_to_3m: amber,
|
||||
from_1w_to_1m: orange,
|
||||
from_1d_to_1w: red,
|
||||
from_1y: green,
|
||||
from_2y: teal,
|
||||
from_4y: indigo,
|
||||
from_10y: violet,
|
||||
from_15y: fuchsia,
|
||||
coinblocksCreated: purple,
|
||||
coinblocksDestroyed: red,
|
||||
coinblocksStored: green,
|
||||
momentumGreen: green,
|
||||
momentumYellow: yellow,
|
||||
momentumRed: red,
|
||||
probability0_1p: red,
|
||||
probability0_5p: orange,
|
||||
probability1p: yellow,
|
||||
epoch_1: red,
|
||||
epoch_2: orange,
|
||||
epoch_3: yellow,
|
||||
epoch_4: green,
|
||||
epoch_5: blue,
|
||||
highly_liquid: red,
|
||||
liquid: lime,
|
||||
illiquid: cyan,
|
||||
// 2015: pink,
|
||||
// 2016: red,
|
||||
// 2017: orange,
|
||||
// 2018: amber,
|
||||
// 2019: yellow,
|
||||
// 2020: lime,
|
||||
// 2021: green,
|
||||
// 2022: emerald,
|
||||
// 2023: teal,
|
||||
// 2024: cyan,
|
||||
// 2025: sky,
|
||||
// 2026: blue,
|
||||
// 2027: indigo,
|
||||
// 2028: violet,
|
||||
// 2029: purple,
|
||||
// 2030: fuchsia,
|
||||
|
||||
// r1d: pink,
|
||||
// r1w: red,
|
||||
// r1m: amber,
|
||||
// r3m: yellow,
|
||||
// r6m: lime,
|
||||
// r1y: green,
|
||||
// r2y: emerald,
|
||||
// r3y: teal,
|
||||
// r4y: blue,
|
||||
// r5y: indigo,
|
||||
// r6y: violet,
|
||||
// r8y: purple,
|
||||
// r10y: fuchsia,
|
||||
|
||||
// p2pk: lime,
|
||||
// p2pkh: violet,
|
||||
// p2sh: emerald,
|
||||
// p2wpkh: cyan,
|
||||
// p2wsh: pink,
|
||||
// p2tr: blue,
|
||||
// crab: red,
|
||||
// fish: lime,
|
||||
// humpback: violet,
|
||||
// plankton: emerald,
|
||||
// shark: cyan,
|
||||
// shrimp: pink,
|
||||
// whale: blue,
|
||||
// megalodon: purple,
|
||||
// realizedPrice: orange,
|
||||
// oneMonthHolders: cyan,
|
||||
// threeMonthsHolders: lime,
|
||||
// sth: yellow,
|
||||
// sixMonthsHolder: red,
|
||||
// oneYearHolders: pink,
|
||||
// twoYearsHolders: purple,
|
||||
// lth: fuchsia,
|
||||
// balancedPrice: yellow,
|
||||
// cointimePrice: yellow,
|
||||
// trueMarketMeanPrice: blue,
|
||||
// vaultedPrice: green,
|
||||
// cvdd: lime,
|
||||
// terminalPrice: red,
|
||||
// loss: red,
|
||||
// profit: green,
|
||||
// thermoCap: green,
|
||||
// investorCap: rose,
|
||||
// realizedCap: orange,
|
||||
// offLiveliness: red,
|
||||
// liveliness: rose,
|
||||
// vaultedness: green,
|
||||
// activityToVaultednessRatio: violet,
|
||||
// up_to_1d: pink,
|
||||
// up_to_1w: red,
|
||||
// up_to_1m: orange,
|
||||
// up_to_2m: amber,
|
||||
// up_to_3m: yellow,
|
||||
// up_to_4m: lime,
|
||||
// up_to_5m: green,
|
||||
// up_to_6m: teal,
|
||||
// up_to_1y: sky,
|
||||
// up_to_2y: indigo,
|
||||
// up_to_3y: violet,
|
||||
// up_to_4y: purple,
|
||||
// up_to_5y: red,
|
||||
// up_to_7y: orange,
|
||||
// up_to_10y: amber,
|
||||
// up_to_15y: yellow,
|
||||
// from_10y_to_15y: purple,
|
||||
// from_7y_to_10y: violet,
|
||||
// from_5y_to_7y: indigo,
|
||||
// from_3y_to_5y: sky,
|
||||
// from_2y_to_3y: teal,
|
||||
// from_1y_to_2y: green,
|
||||
// from_6m_to_1y: lime,
|
||||
// from_3m_to_6m: yellow,
|
||||
// from_1m_to_3m: amber,
|
||||
// from_1w_to_1m: orange,
|
||||
// from_1d_to_1w: red,
|
||||
// from_1y: green,
|
||||
// from_2y: teal,
|
||||
// from_4y: indigo,
|
||||
// from_10y: violet,
|
||||
// from_15y: fuchsia,
|
||||
// coinblocksCreated: purple,
|
||||
// coinblocksDestroyed: red,
|
||||
// coinblocksStored: green,
|
||||
// momentumGreen: green,
|
||||
// momentumYellow: yellow,
|
||||
// momentumRed: red,
|
||||
// probability0_1p: red,
|
||||
// probability0_5p: orange,
|
||||
// probability1p: yellow,
|
||||
// epoch_1: red,
|
||||
// epoch_2: orange,
|
||||
// epoch_3: yellow,
|
||||
// epoch_4: green,
|
||||
// epoch_5: blue,
|
||||
// highly_liquid: red,
|
||||
// liquid: lime,
|
||||
// illiquid: cyan,
|
||||
};
|
||||
}
|
||||
/**
|
||||
|
||||
+1690
-110
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user