mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-27 22:44:30 -07:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 18fb2e7d4d | |||
| a610fd53e2 | |||
| 16abce1f2d | |||
| f3b42f34a6 | |||
| 6483d324de | |||
| 5ab97050dd | |||
| 17eed70903 | |||
| 88067c03b7 | |||
| 7c1e5b913f | |||
| 0014235e91 | |||
| a39b7be1d1 | |||
| de98c5f706 | |||
| 10b496e845 | |||
| bbe7bf390d | |||
| 4777b3400a | |||
| acaa70e944 | |||
| 4049d694f7 | |||
| e155a3dacf | |||
| a224e4c4d8 | |||
| edaeda5424 | |||
| 09d974913d | |||
| f82edb290a |
@@ -64,7 +64,7 @@ jobs:
|
||||
# we specify bash to get pipefail; it guards against the `curl` command
|
||||
# failing. otherwise `sh` won't catch that `curl` returned non-0
|
||||
shell: bash
|
||||
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.29.0/cargo-dist-installer.sh | sh"
|
||||
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.30.0/cargo-dist-installer.sh | sh"
|
||||
- name: Cache dist
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
# Builds
|
||||
target
|
||||
websites/dist
|
||||
vecid-to-indexes.js
|
||||
bridge/
|
||||
/ids.txt
|
||||
|
||||
# Copies
|
||||
|
||||
Generated
+480
-196
File diff suppressed because it is too large
Load Diff
+23
-20
@@ -4,7 +4,7 @@ members = ["crates/*"]
|
||||
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
|
||||
package.license = "MIT"
|
||||
package.edition = "2024"
|
||||
package.version = "0.0.96"
|
||||
package.version = "0.0.106"
|
||||
package.homepage = "https://bitcoinresearchkit.org"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
package.readme = "README.md"
|
||||
@@ -23,29 +23,32 @@ debug = true
|
||||
inherits = "release"
|
||||
|
||||
[workspace.dependencies]
|
||||
allocative = { version = "0.3.4", features = ["parking_lot"] }
|
||||
allocative_derive = "0.3.3"
|
||||
axum = "0.8.4"
|
||||
bitcoin = { version = "0.32.7", features = ["serde"] }
|
||||
bitcoincore-rpc = "0.19.0"
|
||||
brk_bundler = { version = "0.0.96", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.96", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.96", path = "crates/brk_computer" }
|
||||
brk_error = { version = "0.0.96", path = "crates/brk_error" }
|
||||
brk_fetcher = { version = "0.0.96", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.96", path = "crates/brk_indexer" }
|
||||
brk_interface = { version = "0.0.96", path = "crates/brk_interface" }
|
||||
brk_logger = { version = "0.0.96", path = "crates/brk_logger" }
|
||||
brk_mcp = { version = "0.0.96", path = "crates/brk_mcp" }
|
||||
brk_parser = { version = "0.0.96", path = "crates/brk_parser" }
|
||||
brk_server = { version = "0.0.96", path = "crates/brk_server" }
|
||||
brk_store = { version = "0.0.96", path = "crates/brk_store" }
|
||||
brk_structs = { version = "0.0.96", path = "crates/brk_structs" }
|
||||
brk_bundler = { version = "0.0.106", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.106", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.106", path = "crates/brk_computer" }
|
||||
brk_error = { version = "0.0.106", path = "crates/brk_error" }
|
||||
brk_fetcher = { version = "0.0.106", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.106", path = "crates/brk_indexer" }
|
||||
brk_interface = { version = "0.0.106", path = "crates/brk_interface" }
|
||||
brk_logger = { version = "0.0.106", path = "crates/brk_logger" }
|
||||
brk_mcp = { version = "0.0.106", path = "crates/brk_mcp" }
|
||||
brk_parser = { version = "0.0.106", path = "crates/brk_parser" }
|
||||
brk_server = { version = "0.0.106", path = "crates/brk_server" }
|
||||
brk_store = { version = "0.0.106", path = "crates/brk_store" }
|
||||
brk_structs = { version = "0.0.106", path = "crates/brk_structs" }
|
||||
byteview = "=0.6.1"
|
||||
derive_deref = "1.1.1"
|
||||
fjall = "2.11.2"
|
||||
jiff = "0.2.15"
|
||||
log = "0.4.27"
|
||||
minreq = { version = "2.14.0", features = ["https", "serde_json"] }
|
||||
log = "0.4.28"
|
||||
minreq = { version = "2.14.1", features = ["https", "serde_json"] }
|
||||
parking_lot = "0.12.4"
|
||||
quick_cache = "0.6.16"
|
||||
rayon = "1.11.0"
|
||||
serde = "1.0.219"
|
||||
serde_bytes = "0.11.17"
|
||||
@@ -53,9 +56,9 @@ serde_derive = "1.0.219"
|
||||
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
|
||||
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
|
||||
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
|
||||
vecdb = { version = "0.2.9", features = ["derive"]}
|
||||
zerocopy = "0.8.26"
|
||||
zerocopy-derive = "0.8.26"
|
||||
vecdb = { version = "0.2.12", features = ["derive"]}
|
||||
zerocopy = "0.8.27"
|
||||
zerocopy-derive = "0.8.27"
|
||||
|
||||
[workspace.metadata.release]
|
||||
shared-version = true
|
||||
@@ -64,7 +67,7 @@ pre-release-commit-message = "release: v{{version}}"
|
||||
tag-message = "release: v{{version}}"
|
||||
|
||||
[workspace.metadata.dist]
|
||||
cargo-dist-version = "0.29.0"
|
||||
cargo-dist-version = "0.30.0"
|
||||
ci = "github"
|
||||
allow-dirty = ["ci"]
|
||||
installers = []
|
||||
|
||||
@@ -64,11 +64,9 @@
|
||||
- miners
|
||||
- maybe xpubs
|
||||
- charts
|
||||
- improve some names and colors
|
||||
- remove `sum` series when it's a duplicate of the `base` (in subsidy for example)
|
||||
- improve names and colors
|
||||
- selected unit sometimes changes when going back end forth
|
||||
- add support for custom charts
|
||||
- separate z-score charts from "realized price" (with their own prices), have 4y, 2y and 1y
|
||||
- price scale format depends on unit, hide digits for sats for example (if/when possible)
|
||||
- table
|
||||
- pagination
|
||||
|
||||
@@ -12,7 +12,7 @@ build = "build.rs"
|
||||
[dependencies]
|
||||
log = { workspace = true }
|
||||
notify = "8.2.0"
|
||||
brk_rolldown = "0.1.4"
|
||||
brk_rolldown = "0.1.5"
|
||||
# brk_rolldown = { path = "../../../rolldown/crates/rolldown"}
|
||||
sugar_path = "1.2.0"
|
||||
tokio = { workspace = true }
|
||||
|
||||
@@ -35,7 +35,9 @@ pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> i
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
bundler.write().await.unwrap();
|
||||
if let Err(error) = bundler.write().await {
|
||||
error!("{error:?}");
|
||||
}
|
||||
|
||||
let absolute_source_index_path = source_path.join("index.html").absolutize();
|
||||
let absolute_source_index_path_clone = absolute_source_index_path.clone();
|
||||
|
||||
@@ -28,7 +28,7 @@ minreq = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = "0.9.5"
|
||||
zip = { version = "4.6.1", default-features = false, features = ["deflate"] }
|
||||
zip = { version = "5.0.0", default-features = false, features = ["deflate"] }
|
||||
|
||||
[[bin]]
|
||||
name = "brk"
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
use std::{fs, io, path::Path};
|
||||
|
||||
use brk_computer::pools;
|
||||
use brk_interface::{Index, Interface};
|
||||
use brk_server::VERSION;
|
||||
|
||||
use crate::website::Website;
|
||||
|
||||
const SCRIPTS: &str = "scripts";
|
||||
const BRIDGE_PATH: &str = "scripts/bridge";
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub trait Bridge {
|
||||
fn generate_bridge_file(&self, website: Website, websites_path: &Path) -> io::Result<()>;
|
||||
fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()>;
|
||||
}
|
||||
|
||||
impl Bridge for Interface<'static> {
|
||||
fn generate_bridge_file(&self, website: Website, websites_path: &Path) -> io::Result<()> {
|
||||
fn generate_bridge_files(&self, website: Website, websites_path: &Path) -> io::Result<()> {
|
||||
if website.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -24,88 +25,130 @@ impl Bridge for Interface<'static> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let path = path.join(SCRIPTS);
|
||||
let path = path.join(BRIDGE_PATH);
|
||||
|
||||
fs::create_dir_all(&path)?;
|
||||
|
||||
let path = path.join(Path::new("vecid-to-indexes.js"));
|
||||
generate_vecs_file(self, &path)?;
|
||||
generate_pools_file(&path)
|
||||
}
|
||||
}
|
||||
|
||||
let indexes = Index::all();
|
||||
fn generate_pools_file(parent: &Path) -> io::Result<()> {
|
||||
let path = parent.join(Path::new("pools.js"));
|
||||
|
||||
let mut contents = format!(
|
||||
"//
|
||||
let pools = pools();
|
||||
|
||||
let mut contents = "//
|
||||
// File auto-generated, any modifications will be overwritten
|
||||
//
|
||||
"
|
||||
.to_string();
|
||||
|
||||
contents += "
|
||||
/** @typedef {ReturnType<typeof createPools>} Pools */
|
||||
/** @typedef {keyof Pools} Pool */
|
||||
|
||||
export function createPools() {
|
||||
return /** @type {const} */ ({
|
||||
";
|
||||
|
||||
let mut sorted_pools: Vec<_> = pools.iter().collect();
|
||||
sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
|
||||
|
||||
contents += &sorted_pools
|
||||
.iter()
|
||||
.map(|pool| {
|
||||
let id = pool.serialized_id();
|
||||
format!(" {id}: \"{}\",", pool.name)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
contents += "\n });\n}\n";
|
||||
|
||||
fs::write(path, contents)
|
||||
}
|
||||
|
||||
fn generate_vecs_file(interface: &Interface<'static>, parent: &Path) -> io::Result<()> {
|
||||
let path = parent.join(Path::new("vecs.js"));
|
||||
|
||||
let indexes = Index::all();
|
||||
|
||||
let mut contents = format!(
|
||||
"//
|
||||
// File auto-generated, any modifications will be overwritten
|
||||
//
|
||||
|
||||
export const VERSION = \"v{VERSION}\";
|
||||
|
||||
"
|
||||
);
|
||||
);
|
||||
|
||||
contents += &indexes
|
||||
contents += &indexes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i_of_i, i)| {
|
||||
// let lowered = i.to_string().to_lowercase();
|
||||
format!("/** @typedef {{{i_of_i}}} {i} */",)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
contents += &format!(
|
||||
"\n\n/** @typedef {{{}}} Index */\n",
|
||||
indexes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i_of_i, i)| {
|
||||
// let lowered = i.to_string().to_lowercase();
|
||||
format!("/** @typedef {{{i_of_i}}} {i} */",)
|
||||
})
|
||||
.map(|i| i.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
.join(" | ")
|
||||
);
|
||||
|
||||
contents += &format!(
|
||||
"\n\n/** @typedef {{{}}} Index */\n",
|
||||
indexes
|
||||
.iter()
|
||||
.map(|i| i.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" | ")
|
||||
);
|
||||
|
||||
contents += "
|
||||
contents += "
|
||||
/** @typedef {ReturnType<typeof createIndexes>} Indexes */
|
||||
|
||||
export function createIndexes() {
|
||||
return {
|
||||
return {
|
||||
";
|
||||
|
||||
contents += &indexes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i_of_i, i)| {
|
||||
let lowered = i.to_string().to_lowercase();
|
||||
format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
contents += &indexes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i_of_i, i)| {
|
||||
let lowered = i.to_string().to_lowercase();
|
||||
format!(" {lowered}: /** @satisfies {{{i}}} */ ({i_of_i}),",)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
contents += " };\n}\n";
|
||||
contents += " };\n}\n";
|
||||
|
||||
contents += "
|
||||
contents += "
|
||||
/** @typedef {ReturnType<typeof createVecIdToIndexes>} VecIdToIndexes
|
||||
/** @typedef {keyof VecIdToIndexes} VecId */
|
||||
|
||||
/**
|
||||
* @returns {Record<any, number[]>}
|
||||
*/
|
||||
* @returns {Record<any, number[]>}
|
||||
*/
|
||||
export function createVecIdToIndexes() {
|
||||
return {
|
||||
return {
|
||||
";
|
||||
|
||||
self.id_to_index_to_vec()
|
||||
.iter()
|
||||
.for_each(|(id, index_to_vec)| {
|
||||
let indexes = index_to_vec
|
||||
.keys()
|
||||
.map(|i| (*i as u8).to_string())
|
||||
// .map(|i| i.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
interface
|
||||
.id_to_index_to_vec()
|
||||
.iter()
|
||||
.for_each(|(id, index_to_vec)| {
|
||||
let indexes = index_to_vec
|
||||
.keys()
|
||||
.map(|i| (*i as u8).to_string())
|
||||
// .map(|i| i.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
contents += &format!(" \"{id}\": [{indexes}],\n");
|
||||
});
|
||||
contents += &format!(" \"{id}\": [{indexes}],\n");
|
||||
});
|
||||
|
||||
contents += " };\n}\n";
|
||||
contents += " };\n}\n";
|
||||
|
||||
fs::write(path, contents)
|
||||
}
|
||||
fs::write(path, contents)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use std::{
|
||||
use bitcoincore_rpc::{self, Auth, Client};
|
||||
use brk_fetcher::Fetcher;
|
||||
use clap::Parser;
|
||||
use clap_derive::Parser;
|
||||
use color_eyre::eyre::eyre;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ pub fn run() -> color_eyre::Result<()> {
|
||||
downloaded_websites_path
|
||||
};
|
||||
|
||||
interface.generate_bridge_file(website, websites_path.as_path())?;
|
||||
interface.generate_bridge_files(website, websites_path.as_path())?;
|
||||
|
||||
Some(bundle(&websites_path, website.to_folder_name(), true).await?)
|
||||
} else {
|
||||
@@ -135,6 +135,8 @@ pub fn run() -> color_eyre::Result<()> {
|
||||
let starting_indexes =
|
||||
indexer.index(&parser, rpc, &exit, config.check_collisions()).unwrap();
|
||||
|
||||
// dbg!(&starting_indexes);
|
||||
|
||||
computer.compute(&indexer, starting_indexes, &exit).unwrap();
|
||||
|
||||
info!("Waiting for new blocks...");
|
||||
|
||||
@@ -2,6 +2,7 @@ use clap_derive::ValueEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, ValueEnum)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Website {
|
||||
None,
|
||||
Bitview,
|
||||
|
||||
@@ -10,6 +10,8 @@ rust-version.workspace = true
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
allocative = { workspace = true }
|
||||
allocative_derive = { workspace = true }
|
||||
bitcoin = { workspace = true }
|
||||
bitcoincore-rpc = { workspace = true }
|
||||
brk_structs = { workspace = true }
|
||||
@@ -17,13 +19,18 @@ brk_error = { workspace = true }
|
||||
brk_fetcher = { workspace = true }
|
||||
brk_indexer = { workspace = true }
|
||||
brk_logger = { workspace = true }
|
||||
brk_store = { workspace = true }
|
||||
brk_parser = { workspace = true }
|
||||
vecdb = { workspace = true }
|
||||
derive_deref = { workspace = true }
|
||||
inferno = "0.12.3"
|
||||
jiff = { workspace = true }
|
||||
log = { workspace = true }
|
||||
num_enum = "0.7.4"
|
||||
pco = "0.4.6"
|
||||
rayon = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
zerocopy = { workspace = true }
|
||||
zerocopy-derive = { workspace = true }
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
use std::{collections::BTreeMap, path::Path, thread};
|
||||
|
||||
use brk_computer::{Computer, pools};
|
||||
use brk_error::Result;
|
||||
use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{AddressBytes, OutputIndex, OutputType};
|
||||
use vecdb::{AnyIterableVec, Exit, VecIterator};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
brk_logger::init(Some(Path::new(".log")))?;
|
||||
|
||||
let exit = Exit::new();
|
||||
exit.set_ctrlc_handler();
|
||||
|
||||
thread::Builder::new()
|
||||
.stack_size(256 * 1024 * 1024)
|
||||
.spawn(move || -> Result<()> {
|
||||
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
|
||||
|
||||
let indexer = Indexer::forced_import(&outputs_dir)?;
|
||||
|
||||
let fetcher = Fetcher::import(true, None)?;
|
||||
|
||||
let computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?;
|
||||
|
||||
let pools = pools();
|
||||
|
||||
let mut res: BTreeMap<&'static str, usize> = BTreeMap::default();
|
||||
|
||||
let vecs = indexer.vecs;
|
||||
let stores = indexer.stores;
|
||||
|
||||
let mut height_to_first_txindex_iter = vecs.height_to_first_txindex.iter();
|
||||
let mut txindex_to_first_outputindex_iter = vecs.txindex_to_first_outputindex.iter();
|
||||
let mut txindex_to_output_count_iter = computer.indexes.txindex_to_output_count.iter();
|
||||
let mut outputindex_to_outputtype_iter = vecs.outputindex_to_outputtype.iter();
|
||||
let mut outputindex_to_typeindex_iter = vecs.outputindex_to_typeindex.iter();
|
||||
let mut p2pk65addressindex_to_p2pk65bytes_iter =
|
||||
vecs.p2pk65addressindex_to_p2pk65bytes.iter();
|
||||
let mut p2pk33addressindex_to_p2pk33bytes_iter =
|
||||
vecs.p2pk33addressindex_to_p2pk33bytes.iter();
|
||||
let mut p2pkhaddressindex_to_p2pkhbytes_iter =
|
||||
vecs.p2pkhaddressindex_to_p2pkhbytes.iter();
|
||||
let mut p2shaddressindex_to_p2shbytes_iter = vecs.p2shaddressindex_to_p2shbytes.iter();
|
||||
let mut p2wpkhaddressindex_to_p2wpkhbytes_iter =
|
||||
vecs.p2wpkhaddressindex_to_p2wpkhbytes.iter();
|
||||
let mut p2wshaddressindex_to_p2wshbytes_iter =
|
||||
vecs.p2wshaddressindex_to_p2wshbytes.iter();
|
||||
let mut p2traddressindex_to_p2trbytes_iter = vecs.p2traddressindex_to_p2trbytes.iter();
|
||||
let mut p2aaddressindex_to_p2abytes_iter = vecs.p2aaddressindex_to_p2abytes.iter();
|
||||
|
||||
let unknown = pools.get_unknown();
|
||||
|
||||
stores
|
||||
.height_to_coinbase_tag
|
||||
.iter()
|
||||
.for_each(|(height, coinbase_tag)| {
|
||||
let txindex = height_to_first_txindex_iter.unwrap_get_inner(height);
|
||||
let outputindex = txindex_to_first_outputindex_iter.unwrap_get_inner(txindex);
|
||||
let outputcount = txindex_to_output_count_iter.unwrap_get_inner(txindex);
|
||||
|
||||
let pool = (*outputindex..(*outputindex + *outputcount))
|
||||
.map(OutputIndex::from)
|
||||
.find_map(|outputindex| {
|
||||
let outputtype =
|
||||
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
|
||||
let typeindex =
|
||||
outputindex_to_typeindex_iter.unwrap_get_inner(outputindex);
|
||||
|
||||
let address = match outputtype {
|
||||
OutputType::P2PK65 => Some(AddressBytes::from(
|
||||
p2pk65addressindex_to_p2pk65bytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2PK33 => Some(AddressBytes::from(
|
||||
p2pk33addressindex_to_p2pk33bytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2PKH => Some(AddressBytes::from(
|
||||
p2pkhaddressindex_to_p2pkhbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2SH => Some(AddressBytes::from(
|
||||
p2shaddressindex_to_p2shbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2WPKH => Some(AddressBytes::from(
|
||||
p2wpkhaddressindex_to_p2wpkhbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2WSH => Some(AddressBytes::from(
|
||||
p2wshaddressindex_to_p2wshbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2TR => Some(AddressBytes::from(
|
||||
p2traddressindex_to_p2trbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2A => Some(AddressBytes::from(
|
||||
p2aaddressindex_to_p2abytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
address
|
||||
.and_then(|address| pools.find_from_address(&address.to_string()))
|
||||
})
|
||||
.or_else(|| pools.find_from_coinbase_tag(&coinbase_tag))
|
||||
.unwrap_or(unknown);
|
||||
|
||||
*res.entry(pool.name).or_default() += 1;
|
||||
});
|
||||
|
||||
let mut v = res.into_iter().map(|(k, v)| (v, k)).collect::<Vec<_>>();
|
||||
v.sort_unstable();
|
||||
println!("{:#?}", v);
|
||||
println!("{:#?}", v.len());
|
||||
|
||||
Ok(())
|
||||
})?
|
||||
.join()
|
||||
.unwrap()
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
use std::path::Path;
|
||||
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{
|
||||
CheckedSub, Date, DateIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch, Height,
|
||||
InputIndex, OutputIndex, Sats, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64,
|
||||
Timestamp, TxIndex, TxVersion, Version, Weight,
|
||||
CheckedSub, Date, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch,
|
||||
Height, InputIndex, MonthIndex, OutputIndex, QuarterIndex, Sats, SemesterIndex, StoredBool,
|
||||
StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Version, WeekIndex,
|
||||
Weight, YearIndex,
|
||||
};
|
||||
use vecdb::{
|
||||
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
|
||||
@@ -20,18 +22,39 @@ use crate::grouped::{
|
||||
use super::{Indexes, indexes, price};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
const TARGET_BLOCKS_PER_DAY: f64 = 144.0;
|
||||
const TARGET_BLOCKS_PER_DAY_F64: f64 = 144.0;
|
||||
const TARGET_BLOCKS_PER_DAY: u64 = 144;
|
||||
const TARGET_BLOCKS_PER_WEEK: u64 = 7 * TARGET_BLOCKS_PER_DAY;
|
||||
const TARGET_BLOCKS_PER_MONTH: u64 = 30 * TARGET_BLOCKS_PER_DAY;
|
||||
const TARGET_BLOCKS_PER_QUARTER: u64 = 3 * TARGET_BLOCKS_PER_MONTH;
|
||||
const TARGET_BLOCKS_PER_SEMESTER: u64 = 2 * TARGET_BLOCKS_PER_QUARTER;
|
||||
const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER;
|
||||
const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
|
||||
pub dateindex_to_block_count_target: LazyVecFrom1<DateIndex, StoredU64, DateIndex, DateIndex>,
|
||||
pub weekindex_to_block_count_target: LazyVecFrom1<WeekIndex, StoredU64, WeekIndex, WeekIndex>,
|
||||
pub monthindex_to_block_count_target:
|
||||
LazyVecFrom1<MonthIndex, StoredU64, MonthIndex, MonthIndex>,
|
||||
pub quarterindex_to_block_count_target:
|
||||
LazyVecFrom1<QuarterIndex, StoredU64, QuarterIndex, QuarterIndex>,
|
||||
pub semesterindex_to_block_count_target:
|
||||
LazyVecFrom1<SemesterIndex, StoredU64, SemesterIndex, SemesterIndex>,
|
||||
pub yearindex_to_block_count_target: LazyVecFrom1<YearIndex, StoredU64, YearIndex, YearIndex>,
|
||||
pub decadeindex_to_block_count_target:
|
||||
LazyVecFrom1<DecadeIndex, StoredU64, DecadeIndex, DecadeIndex>,
|
||||
pub height_to_interval: EagerVec<Height, Timestamp>,
|
||||
pub height_to_vbytes: EagerVec<Height, StoredU64>,
|
||||
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
|
||||
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
|
||||
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
|
||||
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
|
||||
pub indexes_to_1w_block_count: ComputedVecsFromDateIndex<StoredU32>,
|
||||
pub indexes_to_1m_block_count: ComputedVecsFromDateIndex<StoredU32>,
|
||||
pub indexes_to_1y_block_count: ComputedVecsFromDateIndex<StoredU32>,
|
||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
||||
@@ -39,7 +62,6 @@ pub struct Vecs {
|
||||
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
|
||||
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
|
||||
|
||||
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_fee: ComputedValueVecsFromTxindex,
|
||||
@@ -288,7 +310,57 @@ impl Vecs {
|
||||
let txindex_to_fee_rate =
|
||||
EagerVec::forced_import_compressed(&db, "fee_rate", version + VERSION + Version::ZERO)?;
|
||||
|
||||
let dateindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.dateindex_to_dateindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
|
||||
);
|
||||
let weekindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.weekindex_to_weekindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
|
||||
);
|
||||
let monthindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.monthindex_to_monthindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
|
||||
);
|
||||
let quarterindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.quarterindex_to_quarterindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
|
||||
);
|
||||
let semesterindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.semesterindex_to_semesterindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
|
||||
);
|
||||
let yearindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.yearindex_to_yearindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
|
||||
);
|
||||
let decadeindex_to_block_count_target = LazyVecFrom1::init(
|
||||
"block_count_target",
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes.decadeindex_to_decadeindex.boxed_clone(),
|
||||
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
|
||||
);
|
||||
|
||||
let this = Self {
|
||||
dateindex_to_block_count_target,
|
||||
weekindex_to_block_count_target,
|
||||
monthindex_to_block_count_target,
|
||||
quarterindex_to_block_count_target,
|
||||
semesterindex_to_block_count_target,
|
||||
yearindex_to_block_count_target,
|
||||
decadeindex_to_block_count_target,
|
||||
height_to_interval: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"interval",
|
||||
@@ -321,6 +393,30 @@ impl Vecs {
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_1w_block_count: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"1w_block_count",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1m_block_count: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"1m_block_count",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1y_block_count: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"1y_block_count",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_weight",
|
||||
@@ -869,6 +965,54 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1w_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||
7,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1m_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||
30,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1y_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||
365,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
self.height_to_interval.compute_transform(
|
||||
starting_indexes.height,
|
||||
@@ -1538,7 +1682,7 @@ impl Vecs {
|
||||
i,
|
||||
StoredF64::from(
|
||||
(f64::from(block_count_sum)
|
||||
/ (target_multiplier * TARGET_BLOCKS_PER_DAY))
|
||||
/ (target_multiplier * TARGET_BLOCKS_PER_DAY_F64))
|
||||
* f64::from(difficulty_as_hash),
|
||||
),
|
||||
)
|
||||
@@ -1686,6 +1830,13 @@ impl Vecs {
|
||||
&self.txindex_to_weight,
|
||||
&self.dateindex_to_fee_dominance,
|
||||
&self.dateindex_to_subsidy_dominance,
|
||||
&self.dateindex_to_block_count_target,
|
||||
&self.weekindex_to_block_count_target,
|
||||
&self.monthindex_to_block_count_target,
|
||||
&self.quarterindex_to_block_count_target,
|
||||
&self.semesterindex_to_block_count_target,
|
||||
&self.yearindex_to_block_count_target,
|
||||
&self.decadeindex_to_block_count_target,
|
||||
],
|
||||
self.indexes_to_hash_rate.vecs(),
|
||||
self.indexes_to_hash_rate_1w_sma.vecs(),
|
||||
@@ -1694,6 +1845,9 @@ impl Vecs {
|
||||
self.indexes_to_hash_rate_1y_sma.vecs(),
|
||||
self.timeindexes_to_timestamp.vecs(),
|
||||
self.indexes_to_block_count.vecs(),
|
||||
self.indexes_to_1w_block_count.vecs(),
|
||||
self.indexes_to_1m_block_count.vecs(),
|
||||
self.indexes_to_1y_block_count.vecs(),
|
||||
self.indexes_to_block_interval.vecs(),
|
||||
self.indexes_to_block_size.vecs(),
|
||||
self.indexes_to_block_vbytes.vecs(),
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::path::Path;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{StoredI16, StoredU16, Version};
|
||||
use brk_structs::{StoredF32, StoredI16, StoredU16, Version};
|
||||
use vecdb::{AnyCollectableVec, AnyVec, Database, Exit};
|
||||
|
||||
use crate::grouped::Source;
|
||||
@@ -24,9 +24,10 @@ pub struct Vecs {
|
||||
pub constant_2: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_3: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_4: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_38_2: ComputedVecsFromHeight<StoredF32>,
|
||||
pub constant_50: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_61_8: ComputedVecsFromHeight<StoredF32>,
|
||||
pub constant_100: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_144: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_600: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_minus_1: ComputedVecsFromHeight<StoredI16>,
|
||||
pub constant_minus_2: ComputedVecsFromHeight<StoredI16>,
|
||||
@@ -79,6 +80,14 @@ impl Vecs {
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_38_2: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_38_2",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_50: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_50",
|
||||
@@ -87,17 +96,17 @@ impl Vecs {
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_100: ComputedVecsFromHeight::forced_import(
|
||||
constant_61_8: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_100",
|
||||
"constant_61_8",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_144: ComputedVecsFromHeight::forced_import(
|
||||
constant_100: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_144",
|
||||
"constant_100",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
@@ -184,7 +193,6 @@ impl Vecs {
|
||||
(&mut self.constant_4, 4),
|
||||
(&mut self.constant_50, 50),
|
||||
(&mut self.constant_100, 100),
|
||||
(&mut self.constant_144, 144),
|
||||
(&mut self.constant_600, 600),
|
||||
]
|
||||
.into_iter()
|
||||
@@ -233,6 +241,30 @@ impl Vecs {
|
||||
)
|
||||
})?;
|
||||
|
||||
[
|
||||
(&mut self.constant_38_2, 38.2),
|
||||
(&mut self.constant_61_8, 61.8),
|
||||
]
|
||||
.into_iter()
|
||||
.try_for_each(|(vec, value)| {
|
||||
vec.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, StoredF32::from(value)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -243,9 +275,10 @@ impl Vecs {
|
||||
self.constant_2.vecs(),
|
||||
self.constant_3.vecs(),
|
||||
self.constant_4.vecs(),
|
||||
self.constant_38_2.vecs(),
|
||||
self.constant_50.vecs(),
|
||||
self.constant_61_8.vecs(),
|
||||
self.constant_100.vecs(),
|
||||
self.constant_144.vecs(),
|
||||
self.constant_600.vecs(),
|
||||
self.constant_minus_1.vecs(),
|
||||
self.constant_minus_2.vecs(),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::{Error, Result};
|
||||
use brk_structs::{CheckedSub, StoredU64, Version};
|
||||
use vecdb::{
|
||||
@@ -9,7 +10,7 @@ use crate::utils::get_percentile;
|
||||
|
||||
use super::ComputedType;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Allocative)]
|
||||
pub struct EagerVecBuilder<I, T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
@@ -19,11 +20,11 @@ where
|
||||
pub average: Option<Box<EagerVec<I, T>>>,
|
||||
pub sum: Option<Box<EagerVec<I, T>>>,
|
||||
pub max: Option<Box<EagerVec<I, T>>>,
|
||||
pub p90: Option<Box<EagerVec<I, T>>>,
|
||||
pub p75: Option<Box<EagerVec<I, T>>>,
|
||||
pub pct90: Option<Box<EagerVec<I, T>>>,
|
||||
pub pct75: Option<Box<EagerVec<I, T>>>,
|
||||
pub median: Option<Box<EagerVec<I, T>>>,
|
||||
pub p25: Option<Box<EagerVec<I, T>>>,
|
||||
pub p10: Option<Box<EagerVec<I, T>>>,
|
||||
pub pct25: Option<Box<EagerVec<I, T>>>,
|
||||
pub pct10: Option<Box<EagerVec<I, T>>>,
|
||||
pub min: Option<Box<EagerVec<I, T>>>,
|
||||
pub last: Option<Box<EagerVec<I, T>>>,
|
||||
pub cumulative: Option<Box<EagerVec<I, T>>>,
|
||||
@@ -151,44 +152,44 @@ where
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
p90: options.p90.then(|| {
|
||||
pct90: options.pct90.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("p90"),
|
||||
&maybe_suffix("pct90"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
p75: options.p75.then(|| {
|
||||
pct75: options.pct75.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("p75"),
|
||||
&maybe_suffix("pct75"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
p25: options.p25.then(|| {
|
||||
pct25: options.pct25.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("p25"),
|
||||
&maybe_suffix("pct25"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
p10: options.p10.then(|| {
|
||||
pct10: options.pct10.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("p10"),
|
||||
&maybe_suffix("pct10"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
@@ -292,11 +293,11 @@ where
|
||||
let needs_average_sum_or_cumulative =
|
||||
needs_sum_or_cumulative || self.average.is_some();
|
||||
let needs_sorted = self.max.is_some()
|
||||
|| self.p90.is_some()
|
||||
|| self.p75.is_some()
|
||||
|| self.pct90.is_some()
|
||||
|| self.pct75.is_some()
|
||||
|| self.median.is_some()
|
||||
|| self.p25.is_some()
|
||||
|| self.p10.is_some()
|
||||
|| self.pct25.is_some()
|
||||
|| self.pct10.is_some()
|
||||
|| self.min.is_some();
|
||||
let needs_values = needs_sorted || needs_average_sum_or_cumulative;
|
||||
|
||||
@@ -333,24 +334,24 @@ where
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(p90) = self.p90.as_mut() {
|
||||
p90.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
|
||||
if let Some(pct90) = self.pct90.as_mut() {
|
||||
pct90.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
|
||||
}
|
||||
|
||||
if let Some(p75) = self.p75.as_mut() {
|
||||
p75.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
|
||||
if let Some(pct75) = self.pct75.as_mut() {
|
||||
pct75.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
|
||||
}
|
||||
|
||||
if let Some(median) = self.median.as_mut() {
|
||||
median.forced_push_at(index, get_percentile(&values, 0.50), exit)?;
|
||||
}
|
||||
|
||||
if let Some(p25) = self.p25.as_mut() {
|
||||
p25.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
|
||||
if let Some(pct25) = self.pct25.as_mut() {
|
||||
pct25.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
|
||||
}
|
||||
|
||||
if let Some(p10) = self.p10.as_mut() {
|
||||
p10.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
|
||||
if let Some(pct10) = self.pct10.as_mut() {
|
||||
pct10.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
|
||||
}
|
||||
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
@@ -401,11 +402,11 @@ where
|
||||
where
|
||||
I2: StoredIndex + StoredRaw + CheckedSub<I2>,
|
||||
{
|
||||
if self.p90.is_some()
|
||||
|| self.p75.is_some()
|
||||
if self.pct90.is_some()
|
||||
|| self.pct75.is_some()
|
||||
|| self.median.is_some()
|
||||
|| self.p25.is_some()
|
||||
|| self.p10.is_some()
|
||||
|| self.pct25.is_some()
|
||||
|| self.pct10.is_some()
|
||||
{
|
||||
panic!("unsupported");
|
||||
}
|
||||
@@ -558,24 +559,24 @@ where
|
||||
self.max.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_p90(&self) -> &EagerVec<I, T> {
|
||||
self.p90.as_ref().unwrap()
|
||||
pub fn unwrap_pct90(&self) -> &EagerVec<I, T> {
|
||||
self.pct90.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_p75(&self) -> &EagerVec<I, T> {
|
||||
self.p75.as_ref().unwrap()
|
||||
pub fn unwrap_pct75(&self) -> &EagerVec<I, T> {
|
||||
self.pct75.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_median(&self) -> &EagerVec<I, T> {
|
||||
self.median.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_p25(&self) -> &EagerVec<I, T> {
|
||||
self.p25.as_ref().unwrap()
|
||||
pub fn unwrap_pct25(&self) -> &EagerVec<I, T> {
|
||||
self.pct25.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_p10(&self) -> &EagerVec<I, T> {
|
||||
self.p10.as_ref().unwrap()
|
||||
pub fn unwrap_pct10(&self) -> &EagerVec<I, T> {
|
||||
self.pct10.as_ref().unwrap()
|
||||
}
|
||||
pub fn unwrap_min(&self) -> &EagerVec<I, T> {
|
||||
self.min.as_ref().unwrap()
|
||||
@@ -615,17 +616,17 @@ where
|
||||
if let Some(cumulative) = self.cumulative.as_ref() {
|
||||
v.push(cumulative.as_ref());
|
||||
}
|
||||
if let Some(p90) = self.p90.as_ref() {
|
||||
v.push(p90.as_ref());
|
||||
if let Some(pct90) = self.pct90.as_ref() {
|
||||
v.push(pct90.as_ref());
|
||||
}
|
||||
if let Some(p75) = self.p75.as_ref() {
|
||||
v.push(p75.as_ref());
|
||||
if let Some(pct75) = self.pct75.as_ref() {
|
||||
v.push(pct75.as_ref());
|
||||
}
|
||||
if let Some(p25) = self.p25.as_ref() {
|
||||
v.push(p25.as_ref());
|
||||
if let Some(pct25) = self.pct25.as_ref() {
|
||||
v.push(pct25.as_ref());
|
||||
}
|
||||
if let Some(p10) = self.p10.as_ref() {
|
||||
v.push(p10.as_ref());
|
||||
if let Some(pct10) = self.pct10.as_ref() {
|
||||
v.push(pct10.as_ref());
|
||||
}
|
||||
|
||||
v
|
||||
@@ -656,17 +657,17 @@ where
|
||||
if let Some(cumulative) = self.cumulative.as_mut() {
|
||||
cumulative.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(p90) = self.p90.as_mut() {
|
||||
p90.safe_flush(exit)?;
|
||||
if let Some(pct90) = self.pct90.as_mut() {
|
||||
pct90.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(p75) = self.p75.as_mut() {
|
||||
p75.safe_flush(exit)?;
|
||||
if let Some(pct75) = self.pct75.as_mut() {
|
||||
pct75.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(p25) = self.p25.as_mut() {
|
||||
p25.safe_flush(exit)?;
|
||||
if let Some(pct25) = self.pct25.as_mut() {
|
||||
pct25.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(p10) = self.p10.as_mut() {
|
||||
p10.safe_flush(exit)?;
|
||||
if let Some(pct10) = self.pct10.as_mut() {
|
||||
pct10.safe_flush(exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -697,17 +698,17 @@ where
|
||||
if let Some(cumulative) = self.cumulative.as_mut() {
|
||||
cumulative.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(p90) = self.p90.as_mut() {
|
||||
p90.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(pct90) = self.pct90.as_mut() {
|
||||
pct90.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(p75) = self.p75.as_mut() {
|
||||
p75.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(pct75) = self.pct75.as_mut() {
|
||||
pct75.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(p25) = self.p25.as_mut() {
|
||||
p25.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(pct25) = self.pct25.as_mut() {
|
||||
pct25.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(p10) = self.p10.as_mut() {
|
||||
p10.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(pct10) = self.pct10.as_mut() {
|
||||
pct10.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -719,11 +720,11 @@ pub struct VecBuilderOptions {
|
||||
average: bool,
|
||||
sum: bool,
|
||||
max: bool,
|
||||
p90: bool,
|
||||
p75: bool,
|
||||
pct90: bool,
|
||||
pct75: bool,
|
||||
median: bool,
|
||||
p25: bool,
|
||||
p10: bool,
|
||||
pct25: bool,
|
||||
pct10: bool,
|
||||
min: bool,
|
||||
first: bool,
|
||||
last: bool,
|
||||
@@ -743,24 +744,24 @@ impl VecBuilderOptions {
|
||||
self.max
|
||||
}
|
||||
|
||||
pub fn p90(&self) -> bool {
|
||||
self.p90
|
||||
pub fn pct90(&self) -> bool {
|
||||
self.pct90
|
||||
}
|
||||
|
||||
pub fn p75(&self) -> bool {
|
||||
self.p75
|
||||
pub fn pct75(&self) -> bool {
|
||||
self.pct75
|
||||
}
|
||||
|
||||
pub fn median(&self) -> bool {
|
||||
self.median
|
||||
}
|
||||
|
||||
pub fn p25(&self) -> bool {
|
||||
self.p25
|
||||
pub fn pct25(&self) -> bool {
|
||||
self.pct25
|
||||
}
|
||||
|
||||
pub fn p10(&self) -> bool {
|
||||
self.p10
|
||||
pub fn pct10(&self) -> bool {
|
||||
self.pct10
|
||||
}
|
||||
|
||||
pub fn min(&self) -> bool {
|
||||
@@ -816,26 +817,26 @@ impl VecBuilderOptions {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_p90(mut self) -> Self {
|
||||
self.p90 = true;
|
||||
pub fn add_pct90(mut self) -> Self {
|
||||
self.pct90 = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_p75(mut self) -> Self {
|
||||
self.p75 = true;
|
||||
pub fn add_pct75(mut self) -> Self {
|
||||
self.pct75 = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_p25(mut self) -> Self {
|
||||
self.p25 = true;
|
||||
pub fn add_pct25(mut self) -> Self {
|
||||
self.pct25 = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_p10(mut self) -> Self {
|
||||
self.p10 = true;
|
||||
pub fn add_pct10(mut self) -> Self {
|
||||
self.pct10 = true;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -875,26 +876,26 @@ impl VecBuilderOptions {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_p90(mut self) -> Self {
|
||||
self.p90 = false;
|
||||
pub fn rm_pct90(mut self) -> Self {
|
||||
self.pct90 = false;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_p75(mut self) -> Self {
|
||||
self.p75 = false;
|
||||
pub fn rm_pct75(mut self) -> Self {
|
||||
self.pct75 = false;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_p25(mut self) -> Self {
|
||||
self.p25 = false;
|
||||
pub fn rm_pct25(mut self) -> Self {
|
||||
self.pct25 = false;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_p10(mut self) -> Self {
|
||||
self.p10 = false;
|
||||
pub fn rm_pct10(mut self) -> Self {
|
||||
self.pct10 = false;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -911,20 +912,20 @@ impl VecBuilderOptions {
|
||||
}
|
||||
|
||||
pub fn add_percentiles(mut self) -> Self {
|
||||
self.p90 = true;
|
||||
self.p75 = true;
|
||||
self.pct90 = true;
|
||||
self.pct75 = true;
|
||||
self.median = true;
|
||||
self.p25 = true;
|
||||
self.p10 = true;
|
||||
self.pct25 = true;
|
||||
self.pct10 = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn remove_percentiles(mut self) -> Self {
|
||||
self.p90 = false;
|
||||
self.p75 = false;
|
||||
self.pct90 = false;
|
||||
self.pct75 = false;
|
||||
self.median = false;
|
||||
self.p25 = false;
|
||||
self.p10 = false;
|
||||
self.pct25 = false;
|
||||
self.pct10 = false;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -933,11 +934,11 @@ impl VecBuilderOptions {
|
||||
self.average,
|
||||
self.sum,
|
||||
self.max,
|
||||
self.p90,
|
||||
self.p75,
|
||||
self.pct90,
|
||||
self.pct75,
|
||||
self.median,
|
||||
self.p25,
|
||||
self.p10,
|
||||
self.pct25,
|
||||
self.pct10,
|
||||
self.min,
|
||||
self.first,
|
||||
self.last,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_structs::Version;
|
||||
use vecdb::{
|
||||
AnyBoxedIterableVec, AnyCloneableIterableVec, AnyCollectableVec, FromCoarserIndex,
|
||||
@@ -9,7 +10,7 @@ use crate::grouped::{EagerVecBuilder, VecBuilderOptions};
|
||||
use super::ComputedType;
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct LazyVecBuilder<I, T, S1I, S2T>
|
||||
where
|
||||
I: StoredIndex,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_indexer::Indexer;
|
||||
@@ -10,7 +11,7 @@ use crate::{Indexes, grouped::LazyVecBuilder, indexes};
|
||||
|
||||
use super::{ComputedType, EagerVecBuilder, Source, VecBuilderOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct ComputedVecsFromDateIndex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
|
||||
use brk_indexer::Indexer;
|
||||
@@ -15,7 +16,7 @@ use crate::{
|
||||
|
||||
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct ComputedVecsFromHeight<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{
|
||||
@@ -17,7 +18,7 @@ use crate::{
|
||||
|
||||
use super::{ComputedType, EagerVecBuilder, VecBuilderOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct ComputedVecsFromTxindex<T>
|
||||
where
|
||||
T: ComputedType + PartialOrd,
|
||||
@@ -319,24 +320,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_90p) = self.height.p90.as_mut() {
|
||||
_90p.forced_push_at(
|
||||
if let Some(pct90) = self.height.pct90.as_mut() {
|
||||
pct90.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_p90()
|
||||
.unwrap_pct90()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_75p) = self.height.p75.as_mut() {
|
||||
_75p.forced_push_at(
|
||||
if let Some(pct75) = self.height.pct75.as_mut() {
|
||||
pct75.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_p75()
|
||||
.unwrap_pct75()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
@@ -355,24 +356,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_25p) = self.height.p25.as_mut() {
|
||||
_25p.forced_push_at(
|
||||
if let Some(pct25) = self.height.pct25.as_mut() {
|
||||
pct25.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_p25()
|
||||
.unwrap_pct25()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_10p) = self.height.p10.as_mut() {
|
||||
_10p.forced_push_at(
|
||||
if let Some(pct10) = self.height.pct10.as_mut() {
|
||||
pct10.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_p10()
|
||||
.unwrap_pct10()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
@@ -502,25 +503,25 @@ impl ComputedVecsFromTxindex<Dollars> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_90p) = self.height.p90.as_mut() {
|
||||
_90p.forced_push_at(
|
||||
if let Some(pct90) = self.height.pct90.as_mut() {
|
||||
pct90.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_p90()
|
||||
.unwrap_pct90()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_75p) = self.height.p75.as_mut() {
|
||||
_75p.forced_push_at(
|
||||
if let Some(pct75) = self.height.pct75.as_mut() {
|
||||
pct75.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_p75()
|
||||
.unwrap_pct75()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
@@ -538,25 +539,25 @@ impl ComputedVecsFromTxindex<Dollars> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_25p) = self.height.p25.as_mut() {
|
||||
_25p.forced_push_at(
|
||||
if let Some(pct25) = self.height.pct25.as_mut() {
|
||||
pct25.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_p25()
|
||||
.unwrap_pct25()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_10p) = self.height.p10.as_mut() {
|
||||
_10p.forced_push_at(
|
||||
if let Some(pct10) = self.height.pct10.as_mut() {
|
||||
pct10.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_p10()
|
||||
.unwrap_pct10()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
|
||||
@@ -8,7 +8,9 @@ use vecdb::{
|
||||
|
||||
use crate::{
|
||||
Indexes,
|
||||
grouped::{ComputedStandardDeviationVecsFromDateIndex, source::Source},
|
||||
grouped::{
|
||||
ComputedStandardDeviationVecsFromDateIndex, StandardDeviationVecsOptions, source::Source,
|
||||
},
|
||||
indexes, price,
|
||||
utils::get_percentile,
|
||||
};
|
||||
@@ -105,6 +107,7 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default().add_all(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -116,6 +119,7 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default().add_all(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -127,6 +131,7 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default().add_all(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -138,6 +143,7 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default().add_all(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
@@ -12,7 +13,7 @@ use crate::{
|
||||
|
||||
use super::{ComputedVecsFromHeight, VecBuilderOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct ComputedValueVecsFromHeight {
|
||||
pub sats: ComputedVecsFromHeight<Sats>,
|
||||
pub bitcoin: ComputedVecsFromHeight<Bitcoin>,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{Bitcoin, Close, Dollars, Height, Sats, TxIndex, Version};
|
||||
@@ -10,7 +11,7 @@ use crate::{Indexes, grouped::Source, indexes, price};
|
||||
|
||||
use super::{ComputedVecsFromTxindex, VecBuilderOptions};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct ComputedValueVecsFromTxindex {
|
||||
pub sats: ComputedVecsFromTxindex<Sats>,
|
||||
pub bitcoin_txindex: LazyVecFrom1<TxIndex, Bitcoin, TxIndex, Sats>,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::{path::Path, thread};
|
||||
use std::path::Path;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_fetcher::Fetcher;
|
||||
@@ -16,6 +16,7 @@ mod fetched;
|
||||
mod grouped;
|
||||
mod indexes;
|
||||
mod market;
|
||||
mod pools;
|
||||
mod price;
|
||||
mod stateful;
|
||||
mod states;
|
||||
@@ -24,6 +25,7 @@ mod utils;
|
||||
|
||||
use indexes::Indexes;
|
||||
|
||||
pub use pools::*;
|
||||
pub use states::PriceToAmount;
|
||||
use states::*;
|
||||
|
||||
@@ -32,6 +34,7 @@ pub struct Computer {
|
||||
pub indexes: indexes::Vecs,
|
||||
pub constants: constants::Vecs,
|
||||
pub market: market::Vecs,
|
||||
pub pools: pools::Vecs,
|
||||
pub price: Option<price::Vecs>,
|
||||
pub chain: chain::Vecs,
|
||||
pub stateful: stateful::Vecs,
|
||||
@@ -39,7 +42,7 @@ pub struct Computer {
|
||||
pub cointime: cointime::Vecs,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
const VERSION: Version = Version::new(4);
|
||||
|
||||
impl Computer {
|
||||
/// Do NOT import multiple times or things will break !!!
|
||||
@@ -84,6 +87,12 @@ impl Computer {
|
||||
&indexes,
|
||||
price.as_ref(),
|
||||
)?,
|
||||
pools: pools::Vecs::forced_import(
|
||||
&computed_path,
|
||||
VERSION + Version::ZERO,
|
||||
&indexes,
|
||||
price.as_ref(),
|
||||
)?,
|
||||
cointime: cointime::Vecs::forced_import(
|
||||
&computed_path,
|
||||
VERSION + Version::ZERO,
|
||||
@@ -123,8 +132,8 @@ impl Computer {
|
||||
)?;
|
||||
}
|
||||
|
||||
thread::scope(|scope| -> Result<()> {
|
||||
let chain = scope.spawn(|| {
|
||||
std::thread::scope(|scope| -> Result<()> {
|
||||
let chain = scope.spawn(|| -> Result<()> {
|
||||
info!("Computing chain...");
|
||||
self.chain.compute(
|
||||
indexer,
|
||||
@@ -132,23 +141,31 @@ impl Computer {
|
||||
&starting_indexes,
|
||||
self.price.as_ref(),
|
||||
exit,
|
||||
)
|
||||
});
|
||||
|
||||
let market = scope.spawn(|| -> Result<()> {
|
||||
if let Some(price) = self.price.as_ref() {
|
||||
info!("Computing market...");
|
||||
self.market
|
||||
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
|
||||
}
|
||||
)?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
if let Some(price) = self.price.as_ref() {
|
||||
info!("Computing market...");
|
||||
self.market
|
||||
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
|
||||
}
|
||||
|
||||
chain.join().unwrap()?;
|
||||
market.join().unwrap()?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.pools.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
&self.chain,
|
||||
self.price.as_ref(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// return Ok(());
|
||||
|
||||
info!("Computing stateful...");
|
||||
self.stateful.compute(
|
||||
indexer,
|
||||
@@ -181,6 +198,7 @@ impl Computer {
|
||||
self.chain.vecs(),
|
||||
self.stateful.vecs(),
|
||||
self.cointime.vecs(),
|
||||
self.pools.vecs(),
|
||||
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
self.price.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
@@ -193,3 +211,36 @@ impl Computer {
|
||||
Box::leak(Box::new(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn generate_allocation_files(monitored: &pools::Vecs) -> Result<()> {
|
||||
// info!("Generating Allocative files...");
|
||||
|
||||
// let mut flamegraph = allocative::FlameGraphBuilder::default();
|
||||
// flamegraph.visit_root(monitored);
|
||||
// let output = flamegraph.finish();
|
||||
|
||||
// let folder = format!(
|
||||
// "at-{}",
|
||||
// jiff::Timestamp::now().strftime("%Y-%m-%d_%Hh%Mm%Ss"),
|
||||
// );
|
||||
|
||||
// let path = std::path::PathBuf::from(&format!("./target/flamegraph/{folder}"));
|
||||
// std::fs::create_dir_all(&path)?;
|
||||
|
||||
// // fs::write(path.join("flamegraph.src"), &output.flamegraph())?;
|
||||
|
||||
// let mut fg_svg = Vec::new();
|
||||
// inferno::flamegraph::from_reader(
|
||||
// &mut inferno::flamegraph::Options::default(),
|
||||
// output.flamegraph().write().as_bytes(),
|
||||
// &mut fg_svg,
|
||||
// )?;
|
||||
|
||||
// std::fs::write(path.join("flamegraph.svg"), &fg_svg)?;
|
||||
|
||||
// std::fs::write(path.join("warnings.txt"), output.warnings())?;
|
||||
|
||||
// info!("Successfully generated Allocative files");
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
+590
-155
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,287 @@
|
||||
use allocative::Allocative;
|
||||
use num_enum::{FromPrimitive, IntoPrimitive};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
// Created from the list in `pools.rs`
|
||||
// Can be used as index for said list
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
FromPrimitive,
|
||||
IntoPrimitive,
|
||||
FromBytes,
|
||||
IntoBytes,
|
||||
Immutable,
|
||||
KnownLayout,
|
||||
Allocative,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[repr(u8)]
|
||||
pub enum PoolId {
|
||||
#[default]
|
||||
Unknown,
|
||||
BlockFills,
|
||||
UltimusPool,
|
||||
TerraPool,
|
||||
Luxor,
|
||||
OneThash,
|
||||
BtcCom,
|
||||
Bitfarms,
|
||||
HuobiPool,
|
||||
WayiCn,
|
||||
CanoePool,
|
||||
BtcTop,
|
||||
BitcoinCom,
|
||||
Pool175btc,
|
||||
GbMiners,
|
||||
AXbt,
|
||||
AsicMiner,
|
||||
BitMinter,
|
||||
BitcoinRussia,
|
||||
BtcServ,
|
||||
SimplecoinUs,
|
||||
BtcGuild,
|
||||
Eligius,
|
||||
OzCoin,
|
||||
EclipseMc,
|
||||
MaxBtc,
|
||||
TripleMining,
|
||||
CoinLab,
|
||||
Pool50btc,
|
||||
GhashIo,
|
||||
StMiningCorp,
|
||||
Bitparking,
|
||||
Mmpool,
|
||||
Polmine,
|
||||
KncMiner,
|
||||
Bitalo,
|
||||
F2Pool,
|
||||
Hhtt,
|
||||
MegaBigPower,
|
||||
MtRed,
|
||||
NmcBit,
|
||||
YourbtcNet,
|
||||
GiveMeCoins,
|
||||
BraiinsPool,
|
||||
AntPool,
|
||||
MultiCoinCo,
|
||||
BcpoolIo,
|
||||
Cointerra,
|
||||
KanoPool,
|
||||
SoloCk,
|
||||
CkPool,
|
||||
NiceHash,
|
||||
BitClub,
|
||||
BitcoinAffiliateNetwork,
|
||||
Btcc,
|
||||
BwPool,
|
||||
ExxBw,
|
||||
Bitsolo,
|
||||
BitFury,
|
||||
TwentyOneInc,
|
||||
DigitalBtc,
|
||||
EightBaochi,
|
||||
MyBtcCoinPool,
|
||||
TbDice,
|
||||
HashPool,
|
||||
Nexious,
|
||||
BravoMining,
|
||||
HotPool,
|
||||
OkExPool,
|
||||
BcMonster,
|
||||
OneHash,
|
||||
Bixin,
|
||||
TatmasPool,
|
||||
ViaBtc,
|
||||
ConnectBtc,
|
||||
BatPool,
|
||||
Waterhole,
|
||||
DcExploration,
|
||||
Dcex,
|
||||
BtPool,
|
||||
FiftyEightCoin,
|
||||
BitcoinIndia,
|
||||
ShawnP0wers,
|
||||
PHashIo,
|
||||
RigPool,
|
||||
HaoZhuZhu,
|
||||
SevenPool,
|
||||
MiningKings,
|
||||
HashBx,
|
||||
DPool,
|
||||
Rawpool,
|
||||
Haominer,
|
||||
Helix,
|
||||
BitcoinUkraine,
|
||||
Poolin,
|
||||
SecretSuperstar,
|
||||
TigerpoolNet,
|
||||
SigmapoolCom,
|
||||
OkpoolTop,
|
||||
Hummerpool,
|
||||
Tangpool,
|
||||
BytePool,
|
||||
SpiderPool,
|
||||
NovaBlock,
|
||||
MiningCity,
|
||||
BinancePool,
|
||||
Minerium,
|
||||
LubianCom,
|
||||
Okkong,
|
||||
AaoPool,
|
||||
EmcdPool,
|
||||
FoundryUsa,
|
||||
SbiCrypto,
|
||||
ArkPool,
|
||||
PureBtcCom,
|
||||
MaraPool,
|
||||
KuCoinPool,
|
||||
EntrustCharityPool,
|
||||
OkMiner,
|
||||
Titan,
|
||||
PegaPool,
|
||||
BtcNuggets,
|
||||
CloudHashing,
|
||||
DigitalXMintsy,
|
||||
Telco214,
|
||||
BtcPoolParty,
|
||||
Multipool,
|
||||
TransactionCoinMining,
|
||||
BtcDig,
|
||||
TrickysBtcPool,
|
||||
BtcMp,
|
||||
Eobot,
|
||||
Unomp,
|
||||
Patels,
|
||||
GoGreenLight,
|
||||
EkanemBtc,
|
||||
Canoe,
|
||||
Tiger,
|
||||
OneM1x,
|
||||
Zulupool,
|
||||
SecPool,
|
||||
Ocean,
|
||||
WhitePool,
|
||||
Wk057,
|
||||
FutureBitApolloSolo,
|
||||
CarbonNegative,
|
||||
PortlandHodl,
|
||||
Phoenix,
|
||||
Neopool,
|
||||
MaxiPool,
|
||||
BitFuFuPool,
|
||||
LuckyPool,
|
||||
MiningDutch,
|
||||
PublicPool,
|
||||
MiningSquared,
|
||||
InnopolisTech,
|
||||
BtcLab,
|
||||
Parasite,
|
||||
Dummy158,
|
||||
Dummy159,
|
||||
Dummy160,
|
||||
Dummy161,
|
||||
Dummy162,
|
||||
Dummy163,
|
||||
Dummy164,
|
||||
Dummy165,
|
||||
Dummy166,
|
||||
Dummy167,
|
||||
Dummy168,
|
||||
Dummy169,
|
||||
Dummy170,
|
||||
Dummy171,
|
||||
Dummy172,
|
||||
Dummy173,
|
||||
Dummy174,
|
||||
Dummy175,
|
||||
Dummy176,
|
||||
Dummy177,
|
||||
Dummy178,
|
||||
Dummy179,
|
||||
Dummy180,
|
||||
Dummy181,
|
||||
Dummy182,
|
||||
Dummy183,
|
||||
Dummy184,
|
||||
Dummy185,
|
||||
Dummy186,
|
||||
Dummy187,
|
||||
Dummy188,
|
||||
Dummy189,
|
||||
Dummy190,
|
||||
Dummy191,
|
||||
Dummy192,
|
||||
Dummy193,
|
||||
Dummy194,
|
||||
Dummy195,
|
||||
Dummy196,
|
||||
Dummy197,
|
||||
Dummy198,
|
||||
Dummy199,
|
||||
Dummy200,
|
||||
Dummy201,
|
||||
Dummy202,
|
||||
Dummy203,
|
||||
Dummy204,
|
||||
Dummy205,
|
||||
Dummy206,
|
||||
Dummy207,
|
||||
Dummy208,
|
||||
Dummy209,
|
||||
Dummy210,
|
||||
Dummy211,
|
||||
Dummy212,
|
||||
Dummy213,
|
||||
Dummy214,
|
||||
Dummy215,
|
||||
Dummy216,
|
||||
Dummy217,
|
||||
Dummy218,
|
||||
Dummy219,
|
||||
Dummy220,
|
||||
Dummy221,
|
||||
Dummy222,
|
||||
Dummy223,
|
||||
Dummy224,
|
||||
Dummy225,
|
||||
Dummy226,
|
||||
Dummy227,
|
||||
Dummy228,
|
||||
Dummy229,
|
||||
Dummy230,
|
||||
Dummy231,
|
||||
Dummy232,
|
||||
Dummy233,
|
||||
Dummy234,
|
||||
Dummy235,
|
||||
Dummy236,
|
||||
Dummy237,
|
||||
Dummy238,
|
||||
Dummy239,
|
||||
Dummy240,
|
||||
Dummy241,
|
||||
Dummy242,
|
||||
Dummy243,
|
||||
Dummy244,
|
||||
Dummy245,
|
||||
Dummy246,
|
||||
Dummy247,
|
||||
Dummy248,
|
||||
Dummy249,
|
||||
Dummy250,
|
||||
Dummy251,
|
||||
Dummy252,
|
||||
Dummy253,
|
||||
Dummy254,
|
||||
Dummy255,
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
use std::{collections::BTreeMap, path::Path};
|
||||
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_store::AnyStore;
|
||||
use brk_structs::{AddressBytes, Height, OutputIndex, OutputType};
|
||||
use rayon::prelude::*;
|
||||
use vecdb::{
|
||||
AnyCollectableVec, AnyIterableVec, AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec,
|
||||
PAGE_SIZE, RawVec, StoredIndex, VecIterator, Version,
|
||||
};
|
||||
|
||||
mod id;
|
||||
mod pool;
|
||||
#[allow(clippy::module_inception)]
|
||||
mod pools;
|
||||
mod vecs;
|
||||
|
||||
pub use id::*;
|
||||
pub use pool::*;
|
||||
pub use pools::*;
|
||||
|
||||
use crate::{
|
||||
chain,
|
||||
indexes::{self, Indexes},
|
||||
price,
|
||||
};
|
||||
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
pools: &'static Pools,
|
||||
height_to_pool: RawVec<Height, PoolId>,
|
||||
|
||||
vecs: BTreeMap<PoolId, vecs::Vecs>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
parent_path: &Path,
|
||||
parent_version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let db = Database::open(&parent_path.join("pools"))?;
|
||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
||||
let pools = pools();
|
||||
|
||||
let version = parent_version + Version::new(3) + Version::new(pools.len() as u64);
|
||||
|
||||
let this = Self {
|
||||
height_to_pool: RawVec::forced_import(&db, "pool", version + Version::ZERO)?,
|
||||
vecs: pools
|
||||
.iter()
|
||||
.map(|pool| {
|
||||
vecs::Vecs::forced_import(
|
||||
&db,
|
||||
pool.id,
|
||||
pools,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
price,
|
||||
)
|
||||
.map(|vecs| (pool.id, vecs))
|
||||
})
|
||||
.collect::<Result<BTreeMap<_, _>>>()?,
|
||||
pools,
|
||||
db,
|
||||
};
|
||||
|
||||
this.db.retain_regions(
|
||||
this.vecs()
|
||||
.into_iter()
|
||||
.flat_map(|v| v.region_names())
|
||||
.collect(),
|
||||
)?;
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
chain: &chain::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_(indexer, indexes, starting_indexes, chain, price, exit)?;
|
||||
self.db.flush_then_punch()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
chain: &chain::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_height_to_pool(indexer, indexes, starting_indexes, exit)?;
|
||||
|
||||
self.vecs.par_iter_mut().try_for_each(|(_, vecs)| {
|
||||
vecs.compute(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
&self.height_to_pool,
|
||||
chain,
|
||||
price,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_height_to_pool(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.height_to_pool.validate_computed_version_or_reset(
|
||||
self.height_to_pool.version() + indexer.stores.height_to_coinbase_tag.version(),
|
||||
)?;
|
||||
|
||||
let mut height_to_first_txindex_iter = indexer.vecs.height_to_first_txindex.iter();
|
||||
let mut txindex_to_first_outputindex_iter =
|
||||
indexer.vecs.txindex_to_first_outputindex.iter();
|
||||
let mut txindex_to_output_count_iter = indexes.txindex_to_output_count.iter();
|
||||
let mut outputindex_to_outputtype_iter = indexer.vecs.outputindex_to_outputtype.iter();
|
||||
let mut outputindex_to_typeindex_iter = indexer.vecs.outputindex_to_typeindex.iter();
|
||||
let mut p2pk65addressindex_to_p2pk65bytes_iter =
|
||||
indexer.vecs.p2pk65addressindex_to_p2pk65bytes.iter();
|
||||
let mut p2pk33addressindex_to_p2pk33bytes_iter =
|
||||
indexer.vecs.p2pk33addressindex_to_p2pk33bytes.iter();
|
||||
let mut p2pkhaddressindex_to_p2pkhbytes_iter =
|
||||
indexer.vecs.p2pkhaddressindex_to_p2pkhbytes.iter();
|
||||
let mut p2shaddressindex_to_p2shbytes_iter =
|
||||
indexer.vecs.p2shaddressindex_to_p2shbytes.iter();
|
||||
let mut p2wpkhaddressindex_to_p2wpkhbytes_iter =
|
||||
indexer.vecs.p2wpkhaddressindex_to_p2wpkhbytes.iter();
|
||||
let mut p2wshaddressindex_to_p2wshbytes_iter =
|
||||
indexer.vecs.p2wshaddressindex_to_p2wshbytes.iter();
|
||||
let mut p2traddressindex_to_p2trbytes_iter =
|
||||
indexer.vecs.p2traddressindex_to_p2trbytes.iter();
|
||||
let mut p2aaddressindex_to_p2abytes_iter = indexer.vecs.p2aaddressindex_to_p2abytes.iter();
|
||||
|
||||
let unknown = self.pools.get_unknown();
|
||||
|
||||
let min = starting_indexes
|
||||
.height
|
||||
.unwrap_to_usize()
|
||||
.min(self.height_to_pool.len());
|
||||
|
||||
indexer
|
||||
.stores
|
||||
.height_to_coinbase_tag
|
||||
.iter()
|
||||
.skip(min)
|
||||
.try_for_each(|(height, coinbase_tag)| -> Result<()> {
|
||||
let txindex = height_to_first_txindex_iter.unwrap_get_inner(height);
|
||||
let outputindex = txindex_to_first_outputindex_iter.unwrap_get_inner(txindex);
|
||||
let outputcount = txindex_to_output_count_iter.unwrap_get_inner(txindex);
|
||||
|
||||
let pool = (*outputindex..(*outputindex + *outputcount))
|
||||
.map(OutputIndex::from)
|
||||
.find_map(|outputindex| {
|
||||
let outputtype =
|
||||
outputindex_to_outputtype_iter.unwrap_get_inner(outputindex);
|
||||
let typeindex = outputindex_to_typeindex_iter.unwrap_get_inner(outputindex);
|
||||
|
||||
let address = match outputtype {
|
||||
OutputType::P2PK65 => Some(AddressBytes::from(
|
||||
p2pk65addressindex_to_p2pk65bytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2PK33 => Some(AddressBytes::from(
|
||||
p2pk33addressindex_to_p2pk33bytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2PKH => Some(AddressBytes::from(
|
||||
p2pkhaddressindex_to_p2pkhbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2SH => Some(AddressBytes::from(
|
||||
p2shaddressindex_to_p2shbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2WPKH => Some(AddressBytes::from(
|
||||
p2wpkhaddressindex_to_p2wpkhbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2WSH => Some(AddressBytes::from(
|
||||
p2wshaddressindex_to_p2wshbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2TR => Some(AddressBytes::from(
|
||||
p2traddressindex_to_p2trbytes_iter
|
||||
.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
OutputType::P2A => Some(AddressBytes::from(
|
||||
p2aaddressindex_to_p2abytes_iter.unwrap_get_inner(typeindex.into()),
|
||||
)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
address
|
||||
.and_then(|address| self.pools.find_from_address(&address.to_string()))
|
||||
})
|
||||
.or_else(|| self.pools.find_from_coinbase_tag(&coinbase_tag))
|
||||
.unwrap_or(unknown);
|
||||
|
||||
self.height_to_pool.push_if_needed(height, pool.id)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.height_to_pool.safe_flush(exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.vecs
|
||||
.iter()
|
||||
.flat_map(|(_, vecs)| vecs.vecs())
|
||||
.collect::<Vec<_>>(),
|
||||
vec![&self.height_to_pool],
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
use allocative::Allocative;
|
||||
|
||||
use crate::pools::PoolId;
|
||||
|
||||
#[derive(Debug, Allocative)]
|
||||
pub struct Pool {
|
||||
pub id: PoolId,
|
||||
pub name: &'static str,
|
||||
pub addresses: Box<[&'static str]>,
|
||||
pub tags: Box<[&'static str]>,
|
||||
pub tags_lowercase: Box<[String]>,
|
||||
pub link: &'static str,
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
pub fn serialized_id(&self) -> String {
|
||||
let value = serde_json::to_value(self.id).unwrap();
|
||||
value.as_str().unwrap().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(usize, JSONPool)> for Pool {
|
||||
fn from((index, pool): (usize, JSONPool)) -> Self {
|
||||
Self {
|
||||
id: (index as u8).into(),
|
||||
name: pool.name,
|
||||
addresses: pool.addresses,
|
||||
tags_lowercase: pool
|
||||
.tags
|
||||
.iter()
|
||||
.map(|t| t.to_lowercase())
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice(),
|
||||
tags: pool.tags,
|
||||
link: pool.link,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JSONPool {
|
||||
pub name: &'static str,
|
||||
pub addresses: Box<[&'static str]>,
|
||||
pub tags: Box<[&'static str]>,
|
||||
pub link: &'static str,
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,467 @@
|
||||
use allocative::Allocative;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{Height, Sats, StoredF32, StoredU16, StoredU32};
|
||||
use vecdb::{AnyCollectableVec, AnyIterableVec, Database, Exit, StoredIndex, VecIterator, Version};
|
||||
|
||||
use crate::{
|
||||
PoolId, Pools, chain,
|
||||
grouped::{
|
||||
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source,
|
||||
VecBuilderOptions,
|
||||
},
|
||||
indexes::{self, Indexes},
|
||||
price,
|
||||
};
|
||||
|
||||
#[derive(Clone, Allocative)]
|
||||
pub struct Vecs {
|
||||
id: PoolId,
|
||||
|
||||
indexes_to_blocks_mined: ComputedVecsFromHeight<StoredU32>,
|
||||
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex<StoredU32>,
|
||||
indexes_to_subsidy: ComputedValueVecsFromHeight,
|
||||
indexes_to_fee: ComputedValueVecsFromHeight,
|
||||
indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
indexes_to_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1d_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1w_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1m_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_1y_dominance: ComputedVecsFromDateIndex<StoredF32>,
|
||||
indexes_to_days_since_block: ComputedVecsFromDateIndex<StoredU16>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
db: &Database,
|
||||
id: PoolId,
|
||||
pools: &Pools,
|
||||
parent_version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let pool = pools.get(id);
|
||||
let name = pool.serialized_id();
|
||||
let suffix = |s: &str| format!("{name}_{s}");
|
||||
let compute_dollars = price.is_some();
|
||||
let version = parent_version + Version::ZERO;
|
||||
|
||||
Ok(Self {
|
||||
id,
|
||||
indexes_to_blocks_mined: ComputedVecsFromHeight::forced_import(
|
||||
db,
|
||||
&suffix("blocks_mined"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_1w_blocks_mined: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1w_blocks_mined"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1m_blocks_mined: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1m_blocks_mined"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1y_blocks_mined: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1y_blocks_mined"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_subsidy: ComputedValueVecsFromHeight::forced_import(
|
||||
db,
|
||||
&suffix("subsidy"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
compute_dollars,
|
||||
indexes,
|
||||
)?,
|
||||
indexes_to_fee: ComputedValueVecsFromHeight::forced_import(
|
||||
db,
|
||||
&suffix("fee"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
compute_dollars,
|
||||
indexes,
|
||||
)?,
|
||||
indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import(
|
||||
db,
|
||||
&suffix("coinbase"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
compute_dollars,
|
||||
indexes,
|
||||
)?,
|
||||
indexes_to_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("dominance"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1d_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1d_dominance"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1w_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1w_dominance"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1m_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1m_dominance"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1y_dominance: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("1y_dominance"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_days_since_block: ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("days_since_block"),
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_pool: &impl AnyIterableVec<Height, PoolId>,
|
||||
chain: &chain::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.indexes_to_blocks_mined.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
height_to_pool,
|
||||
|(h, id, ..)| {
|
||||
(
|
||||
h,
|
||||
if id == self.id {
|
||||
StoredU32::ONE
|
||||
} else {
|
||||
StoredU32::ZERO
|
||||
},
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1w_blocks_mined.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||
7,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1m_blocks_mined.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||
30,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1y_blocks_mined.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||
365,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let height_to_blocks_mined = self.indexes_to_blocks_mined.height.as_ref().unwrap();
|
||||
|
||||
self.indexes_to_subsidy.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
height_to_blocks_mined,
|
||||
chain.indexes_to_subsidy.sats.height.as_ref().unwrap(),
|
||||
|(h, mined, sats, ..)| {
|
||||
(
|
||||
h,
|
||||
if mined == StoredU32::ONE {
|
||||
sats
|
||||
} else {
|
||||
Sats::ZERO
|
||||
},
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_fee.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
height_to_blocks_mined,
|
||||
chain.indexes_to_fee.sats.height.unwrap_sum(),
|
||||
|(h, mined, sats, ..)| {
|
||||
(
|
||||
h,
|
||||
if mined == StoredU32::ONE {
|
||||
sats
|
||||
} else {
|
||||
Sats::ZERO
|
||||
},
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_coinbase.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
height_to_blocks_mined,
|
||||
chain.indexes_to_coinbase.sats.height.as_ref().unwrap(),
|
||||
|(h, mined, sats, ..)| {
|
||||
(
|
||||
h,
|
||||
if mined == StoredU32::ONE {
|
||||
sats
|
||||
} else {
|
||||
Sats::ZERO
|
||||
},
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_dominance.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_cumulative(),
|
||||
chain.indexes_to_block_count.dateindex.unwrap_cumulative(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1d_dominance.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||
chain.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1w_dominance.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_1w_blocks_mined.dateindex.as_ref().unwrap(),
|
||||
chain.indexes_to_1w_block_count.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1m_dominance.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_1m_blocks_mined.dateindex.as_ref().unwrap(),
|
||||
chain.indexes_to_1m_block_count.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_1y_dominance.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_1y_blocks_mined.dateindex.as_ref().unwrap(),
|
||||
chain.indexes_to_1y_block_count.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_days_since_block.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
let mut prev = None;
|
||||
v.compute_transform2(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_sum(),
|
||||
self.indexes_to_blocks_mined.dateindex.unwrap_cumulative(),
|
||||
|(i, sum, cumulative, slf)| {
|
||||
if prev.is_none() {
|
||||
let i = i.unwrap_to_usize();
|
||||
prev.replace(if i > 0 {
|
||||
slf.into_iter().unwrap_get_inner_(i - 1)
|
||||
} else {
|
||||
StoredU16::ZERO
|
||||
});
|
||||
}
|
||||
let days = if !cumulative.is_zero() && sum.is_zero() {
|
||||
prev.unwrap() + StoredU16::ONE
|
||||
} else {
|
||||
StoredU16::ZERO
|
||||
};
|
||||
prev.replace(days);
|
||||
(i, days)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.indexes_to_blocks_mined.vecs(),
|
||||
self.indexes_to_1w_blocks_mined.vecs(),
|
||||
self.indexes_to_1m_blocks_mined.vecs(),
|
||||
self.indexes_to_1y_blocks_mined.vecs(),
|
||||
self.indexes_to_subsidy.vecs(),
|
||||
self.indexes_to_fee.vecs(),
|
||||
self.indexes_to_coinbase.vecs(),
|
||||
self.indexes_to_dominance.vecs(),
|
||||
self.indexes_to_1d_dominance.vecs(),
|
||||
self.indexes_to_1w_dominance.vecs(),
|
||||
self.indexes_to_1m_dominance.vecs(),
|
||||
self.indexes_to_1y_dominance.vecs(),
|
||||
self.indexes_to_days_since_block.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@@ -50,12 +50,12 @@ pub struct Vecs {
|
||||
|
||||
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub dateindex_to_sopr: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_sopr_7d_ema: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_sopr_30d_ema: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_adjusted_sopr: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_adjusted_sopr_7d_ema: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_adjusted_sopr_30d_ema: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_sopr: Option<EagerVec<DateIndex, StoredF64>>,
|
||||
pub dateindex_to_sopr_7d_ema: Option<EagerVec<DateIndex, StoredF64>>,
|
||||
pub dateindex_to_sopr_30d_ema: Option<EagerVec<DateIndex, StoredF64>>,
|
||||
pub dateindex_to_adjusted_sopr: Option<EagerVec<DateIndex, StoredF64>>,
|
||||
pub dateindex_to_adjusted_sopr_7d_ema: Option<EagerVec<DateIndex, StoredF64>>,
|
||||
pub dateindex_to_adjusted_sopr_30d_ema: Option<EagerVec<DateIndex, StoredF64>>,
|
||||
pub indexes_to_realized_cap_30d_delta: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub dateindex_to_sell_side_risk_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_sell_side_risk_ratio_7d_ema: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
@@ -77,8 +77,10 @@ pub struct Vecs {
|
||||
pub indexes_to_value_destroyed: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
pub indexes_to_unrealized_profit: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub indexes_to_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub height_to_unrealized_total_pnl: Option<EagerVec<Height, Dollars>>,
|
||||
pub indexes_to_unrealized_total_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub height_to_total_unrealized_pnl: Option<EagerVec<Height, Dollars>>,
|
||||
pub indexes_to_total_unrealized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub height_to_total_realized_pnl: Option<EagerVec<Height, Dollars>>,
|
||||
pub indexes_to_total_realized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub indexes_to_min_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
pub indexes_to_max_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
pub height_to_supply_half_value: ComputedHeightValueVecs,
|
||||
@@ -110,21 +112,21 @@ pub struct Vecs {
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_net_unrealized_pnl_rel_to_own_market_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub height_to_unrealized_profit_rel_to_own_unrealized_total_pnl:
|
||||
pub height_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
|
||||
Option<EagerVec<Height, StoredF32>>,
|
||||
pub height_to_unrealized_loss_rel_to_own_unrealized_total_pnl:
|
||||
pub height_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
|
||||
Option<EagerVec<Height, StoredF32>>,
|
||||
pub height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl:
|
||||
pub height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
|
||||
Option<EagerVec<Height, StoredF32>>,
|
||||
pub height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl:
|
||||
pub height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
|
||||
Option<EagerVec<Height, StoredF32>>,
|
||||
pub indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl:
|
||||
pub indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl:
|
||||
pub indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl:
|
||||
pub indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl:
|
||||
pub indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_realized_cap_rel_to_own_market_cap: Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub indexes_to_realized_profit_rel_to_realized_cap: Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
@@ -370,18 +372,18 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_unrealized_total_pnl: compute_dollars.then(|| {
|
||||
height_to_total_unrealized_pnl: compute_dollars.then(|| {
|
||||
EagerVec::forced_import_compressed(
|
||||
db,
|
||||
&suffix("unrealized_total_pnl"),
|
||||
&suffix("total_unrealized_pnl"),
|
||||
version + VERSION + Version::ZERO,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_unrealized_total_pnl: compute_dollars.then(|| {
|
||||
indexes_to_total_unrealized_pnl: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("unrealized_total_pnl"),
|
||||
&suffix("total_unrealized_pnl"),
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
@@ -389,6 +391,25 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_total_realized_pnl: compute_dollars.then(|| {
|
||||
EagerVec::forced_import_compressed(
|
||||
db,
|
||||
&suffix("total_realized_pnl"),
|
||||
version + VERSION + Version::ZERO,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_total_realized_pnl: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("total_realized_pnl"),
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ONE,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
dateindex_to_unrealized_loss,
|
||||
height_to_realized_cap: compute_dollars.then(|| {
|
||||
EagerVec::forced_import(
|
||||
@@ -699,7 +720,7 @@ impl Vecs {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("sopr"),
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
@@ -708,7 +729,7 @@ impl Vecs {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("sopr_7d_ema"),
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
@@ -717,7 +738,7 @@ impl Vecs {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("sopr_30d_ema"),
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
@@ -726,7 +747,7 @@ impl Vecs {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("adjusted_sopr"),
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
@@ -735,7 +756,7 @@ impl Vecs {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("adjusted_sopr_7d_ema"),
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
@@ -744,7 +765,7 @@ impl Vecs {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("adjusted_sopr_30d_ema"),
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
@@ -990,56 +1011,56 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_unrealized_profit_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
height_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("unrealized_profit_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("unrealized_profit_rel_to_own_total_unrealized_pnl"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
height_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("unrealized_loss_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("unrealized_loss_rel_to_own_total_unrealized_pnl"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("neg_unrealized_loss_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("net_unrealized_pnl_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("unrealized_profit_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("unrealized_profit_rel_to_own_total_unrealized_pnl"),
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ONE,
|
||||
indexes,
|
||||
@@ -1047,12 +1068,12 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("unrealized_loss_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("unrealized_loss_rel_to_own_total_unrealized_pnl"),
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ONE,
|
||||
indexes,
|
||||
@@ -1060,12 +1081,12 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("neg_unrealized_loss_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ONE,
|
||||
indexes,
|
||||
@@ -1073,12 +1094,12 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl: (compute_dollars
|
||||
indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars
|
||||
&& extended)
|
||||
.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db,
|
||||
&suffix("net_unrealized_pnl_rel_to_own_unrealized_total_pnl"),
|
||||
&suffix("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ONE,
|
||||
indexes,
|
||||
@@ -2673,7 +2694,7 @@ impl Vecs {
|
||||
exit,
|
||||
Some(self.dateindex_to_unrealized_loss.as_ref().unwrap()),
|
||||
)?;
|
||||
self.height_to_unrealized_total_pnl
|
||||
self.height_to_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_add(
|
||||
@@ -2682,7 +2703,7 @@ impl Vecs {
|
||||
self.height_to_unrealized_loss.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
self.indexes_to_unrealized_total_pnl
|
||||
self.indexes_to_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
@@ -2700,6 +2721,41 @@ impl Vecs {
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
self.height_to_total_realized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_add(
|
||||
starting_indexes.height,
|
||||
self.height_to_realized_profit.as_ref().unwrap(),
|
||||
self.height_to_realized_loss.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
self.indexes_to_total_realized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_add(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_realized_profit
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_sum(),
|
||||
self.indexes_to_realized_loss
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_sum(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_min_price_paid
|
||||
.as_mut()
|
||||
@@ -3043,46 +3099,46 @@ impl Vecs {
|
||||
}
|
||||
|
||||
if self
|
||||
.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
|
||||
.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
|
||||
.is_some()
|
||||
{
|
||||
self.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_unrealized_profit.as_ref().unwrap(),
|
||||
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
|
||||
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_unrealized_loss.as_ref().unwrap(),
|
||||
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
|
||||
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_neg_unrealized_loss.as_ref().unwrap(),
|
||||
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
|
||||
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_net_unrealized_pnl.as_ref().unwrap(),
|
||||
self.height_to_unrealized_total_pnl.as_ref().unwrap(),
|
||||
self.height_to_total_unrealized_pnl.as_ref().unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
self.indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
@@ -3094,7 +3150,7 @@ impl Vecs {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.dateindex_to_unrealized_profit.as_ref().unwrap(),
|
||||
self.indexes_to_unrealized_total_pnl
|
||||
self.indexes_to_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
@@ -3105,7 +3161,7 @@ impl Vecs {
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
@@ -3117,7 +3173,7 @@ impl Vecs {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.dateindex_to_unrealized_loss.as_ref().unwrap(),
|
||||
self.indexes_to_unrealized_total_pnl
|
||||
self.indexes_to_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
@@ -3128,7 +3184,7 @@ impl Vecs {
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
@@ -3145,7 +3201,7 @@ impl Vecs {
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
self.indexes_to_unrealized_total_pnl
|
||||
self.indexes_to_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
@@ -3156,7 +3212,7 @@ impl Vecs {
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
self.indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
@@ -3173,7 +3229,7 @@ impl Vecs {
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
self.indexes_to_unrealized_total_pnl
|
||||
self.indexes_to_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
@@ -3806,10 +3862,16 @@ impl Vecs {
|
||||
self.indexes_to_unrealized_loss
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.height_to_unrealized_total_pnl
|
||||
self.height_to_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
self.indexes_to_unrealized_total_pnl
|
||||
self.indexes_to_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.height_to_total_realized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
self.indexes_to_total_realized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_min_price_paid
|
||||
@@ -3843,28 +3905,28 @@ impl Vecs {
|
||||
self.indexes_to_net_unrealized_pnl_rel_to_own_market_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.height_to_unrealized_profit_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
self.height_to_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
self.height_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
self.height_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
|
||||
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
self.indexes_to_unrealized_profit_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_neg_unrealized_loss_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_net_unrealized_pnl_rel_to_own_unrealized_total_pnl
|
||||
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.height_to_neg_unrealized_loss
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct BRK {
|
||||
dateindex_to_ohlc: BTreeMap<DateIndex, Vec<OHLCCents>>,
|
||||
}
|
||||
|
||||
const API_URL: &str = "https://bitcoinresearchkit.org/api/vecs";
|
||||
const API_URL: &str = "https://bitview.space/api/vecs";
|
||||
const CHUNK_SIZE: usize = 10_000;
|
||||
|
||||
impl BRK {
|
||||
@@ -46,7 +46,7 @@ impl BRK {
|
||||
|
||||
default_retry(|_| {
|
||||
let url = format!(
|
||||
"{API_URL}/height-to-ohlc?from={}&to={}",
|
||||
"{API_URL}/height-to-price-ohlc?from={}&to={}",
|
||||
height,
|
||||
height + CHUNK_SIZE
|
||||
);
|
||||
@@ -91,7 +91,7 @@ impl BRK {
|
||||
|
||||
default_retry(|_| {
|
||||
let url = format!(
|
||||
"{API_URL}/dateindex-to-ohlc?from={}&to={}",
|
||||
"{API_URL}/dateindex-to-price-ohlc?from={}&to={}",
|
||||
dateindex,
|
||||
dateindex + CHUNK_SIZE
|
||||
);
|
||||
|
||||
@@ -23,9 +23,12 @@ pub use indexes::*;
|
||||
pub use stores::*;
|
||||
pub use vecs::*;
|
||||
|
||||
// One version for all data sources
|
||||
// Increment on change OR addition
|
||||
const VERSION: Version = Version::new(21);
|
||||
|
||||
const SNAPSHOT_BLOCK_RANGE: usize = 1_000;
|
||||
const COLLISIONS_CHECKED_UP_TO: Height = Height::new(909_150);
|
||||
const VERSION: Version = Version::ONE;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Indexer {
|
||||
@@ -39,10 +42,10 @@ impl Indexer {
|
||||
|
||||
let path = outputs_dir.join("indexed");
|
||||
|
||||
let vecs = Vecs::forced_import(&path, VERSION + Version::ZERO)?;
|
||||
let vecs = Vecs::forced_import(&path, VERSION)?;
|
||||
info!("Imported vecs");
|
||||
|
||||
let stores = Stores::forced_import(&path, VERSION + Version::ZERO)?;
|
||||
let stores = Stores::forced_import(&path, VERSION)?;
|
||||
info!("Imported stores");
|
||||
|
||||
Ok(Self { vecs, stores })
|
||||
|
||||
@@ -27,8 +27,6 @@ pub struct Stores {
|
||||
ByAddressType<Store<TypeIndexWithOutputindex, Unit>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
impl Stores {
|
||||
pub fn forced_import(parent: &Path, version: Version) -> Result<Self> {
|
||||
let path = parent.join("stores");
|
||||
@@ -49,34 +47,21 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"addressbyteshash_to_typeindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
None,
|
||||
)
|
||||
});
|
||||
let blockhashprefix_to_height = scope.spawn(|| {
|
||||
Store::import(
|
||||
&keyspace,
|
||||
&path,
|
||||
"blockhashprefix_to_height",
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
)
|
||||
});
|
||||
let txidprefix_to_txindex = scope.spawn(|| {
|
||||
Store::import(
|
||||
&keyspace,
|
||||
&path,
|
||||
"txidprefix_to_txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
)
|
||||
Store::import(&keyspace, &path, "blockhashprefix_to_height", version, None)
|
||||
});
|
||||
let txidprefix_to_txindex = scope
|
||||
.spawn(|| Store::import(&keyspace, &path, "txidprefix_to_txindex", version, None));
|
||||
let p2aaddressindex_with_outputindex = scope.spawn(|| {
|
||||
Store::import(
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2aaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -85,7 +70,7 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2pk33addressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -94,7 +79,7 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2pk65addressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -103,7 +88,7 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2pkhaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -112,7 +97,7 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2shaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -121,7 +106,7 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2traddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -130,7 +115,7 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2wpkhaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
@@ -139,18 +124,13 @@ impl Stores {
|
||||
&keyspace,
|
||||
&path,
|
||||
"p2wshaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
|
||||
let height_to_coinbase_tag = Store::import(
|
||||
&keyspace,
|
||||
&path,
|
||||
"height_to_coinbase_tag",
|
||||
version + VERSION + Version::ZERO,
|
||||
None,
|
||||
)?;
|
||||
let height_to_coinbase_tag =
|
||||
Store::import(&keyspace, &path, "height_to_coinbase_tag", version, None)?;
|
||||
|
||||
Ok(Self {
|
||||
keyspace: keyspace.clone(),
|
||||
|
||||
+44
-150
@@ -17,8 +17,6 @@ use vecdb::{
|
||||
|
||||
use crate::Indexes;
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
@@ -78,222 +76,118 @@ impl Vecs {
|
||||
db.set_min_len(PAGE_SIZE * 50_000_000)?;
|
||||
|
||||
let this = Self {
|
||||
emptyoutputindex_to_txindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_blockhash: RawVec::forced_import(
|
||||
&db,
|
||||
"blockhash",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_difficulty: CompressedVec::forced_import(
|
||||
&db,
|
||||
"difficulty",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
emptyoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||
height_to_blockhash: RawVec::forced_import(&db, "blockhash", version)?,
|
||||
height_to_difficulty: CompressedVec::forced_import(&db, "difficulty", version)?,
|
||||
height_to_first_emptyoutputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_emptyoutputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_inputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_inputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_opreturnindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_opreturnindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_outputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2aaddressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2aaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2msoutputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2msoutputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2pk33addressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2pk33addressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2pk65addressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2pk65addressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2pkhaddressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2pkhaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2shaddressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2shaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2traddressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2traddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2wpkhaddressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2wpkhaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_p2wshaddressindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_p2wshaddressindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_first_txindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_first_txindex: CompressedVec::forced_import(&db, "first_txindex", version)?,
|
||||
height_to_first_unknownoutputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_unknownoutputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_timestamp: CompressedVec::forced_import(
|
||||
&db,
|
||||
"timestamp",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_total_size: CompressedVec::forced_import(
|
||||
&db,
|
||||
"total_size",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_weight: CompressedVec::forced_import(
|
||||
&db,
|
||||
"weight",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
inputindex_to_outputindex: RawVec::forced_import(
|
||||
&db,
|
||||
"outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
opreturnindex_to_txindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
outputindex_to_outputtype: RawVec::forced_import(
|
||||
&db,
|
||||
"outputtype",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
outputindex_to_typeindex: RawVec::forced_import(
|
||||
&db,
|
||||
"typeindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
outputindex_to_value: RawVec::forced_import(
|
||||
&db,
|
||||
"value",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2aaddressindex_to_p2abytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2abytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2msoutputindex_to_txindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2pk33bytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2pk65bytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2pkhbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2shaddressindex_to_p2shbytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2shbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2traddressindex_to_p2trbytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2trbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2wpkhbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(
|
||||
&db,
|
||||
"p2wshbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
txindex_to_base_size: CompressedVec::forced_import(
|
||||
&db,
|
||||
"base_size",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
height_to_timestamp: CompressedVec::forced_import(&db, "timestamp", version)?,
|
||||
height_to_total_size: CompressedVec::forced_import(&db, "total_size", version)?,
|
||||
height_to_weight: CompressedVec::forced_import(&db, "weight", version)?,
|
||||
inputindex_to_outputindex: RawVec::forced_import(&db, "outputindex", version)?,
|
||||
opreturnindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||
outputindex_to_outputtype: RawVec::forced_import(&db, "outputtype", version)?,
|
||||
outputindex_to_typeindex: RawVec::forced_import(&db, "typeindex", version)?,
|
||||
outputindex_to_value: RawVec::forced_import(&db, "value", version)?,
|
||||
p2aaddressindex_to_p2abytes: RawVec::forced_import(&db, "p2abytes", version)?,
|
||||
p2msoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||
p2pk33addressindex_to_p2pk33bytes: RawVec::forced_import(&db, "p2pk33bytes", version)?,
|
||||
p2pk65addressindex_to_p2pk65bytes: RawVec::forced_import(&db, "p2pk65bytes", version)?,
|
||||
p2pkhaddressindex_to_p2pkhbytes: RawVec::forced_import(&db, "p2pkhbytes", version)?,
|
||||
p2shaddressindex_to_p2shbytes: RawVec::forced_import(&db, "p2shbytes", version)?,
|
||||
p2traddressindex_to_p2trbytes: RawVec::forced_import(&db, "p2trbytes", version)?,
|
||||
p2wpkhaddressindex_to_p2wpkhbytes: RawVec::forced_import(&db, "p2wpkhbytes", version)?,
|
||||
p2wshaddressindex_to_p2wshbytes: RawVec::forced_import(&db, "p2wshbytes", version)?,
|
||||
txindex_to_base_size: CompressedVec::forced_import(&db, "base_size", version)?,
|
||||
txindex_to_first_inputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_inputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
txindex_to_first_outputindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"first_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
txindex_to_is_explicitly_rbf: CompressedVec::forced_import(
|
||||
&db,
|
||||
"is_explicitly_rbf",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
txindex_to_rawlocktime: CompressedVec::forced_import(
|
||||
&db,
|
||||
"rawlocktime",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
txindex_to_total_size: CompressedVec::forced_import(
|
||||
&db,
|
||||
"total_size",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
txindex_to_txid: RawVec::forced_import(&db, "txid", version + VERSION + Version::ZERO)?,
|
||||
txindex_to_txversion: CompressedVec::forced_import(
|
||||
&db,
|
||||
"txversion",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
unknownoutputindex_to_txindex: CompressedVec::forced_import(
|
||||
&db,
|
||||
"txindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
version,
|
||||
)?,
|
||||
txindex_to_rawlocktime: CompressedVec::forced_import(&db, "rawlocktime", version)?,
|
||||
txindex_to_total_size: CompressedVec::forced_import(&db, "total_size", version)?,
|
||||
txindex_to_txid: RawVec::forced_import(&db, "txid", version)?,
|
||||
txindex_to_txversion: CompressedVec::forced_import(&db, "txversion", version)?,
|
||||
unknownoutputindex_to_txindex: CompressedVec::forced_import(&db, "txindex", version)?,
|
||||
|
||||
db,
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ brk_indexer = { workspace = true }
|
||||
brk_structs = { workspace = true }
|
||||
vecdb = { workspace = true }
|
||||
derive_deref = { workspace = true }
|
||||
quick_cache = { workspace = true }
|
||||
schemars = "1.0.4"
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -4,6 +4,7 @@ use serde::Deserialize;
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Format {
|
||||
#[serde(alias = "json")]
|
||||
JSON,
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
use std::fmt;
|
||||
|
||||
use derive_deref::Deref;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deref, JsonSchema)]
|
||||
pub struct MaybeIds(Vec<String>);
|
||||
|
||||
const MAX_VECS: usize = 32;
|
||||
const MAX_STRING_SIZE: usize = 64 * MAX_VECS;
|
||||
|
||||
impl From<String> for MaybeIds {
|
||||
fn from(value: String) -> Self {
|
||||
Self(vec![value])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Vec<&'a str>> for MaybeIds {
|
||||
fn from(value: Vec<&'a str>) -> Self {
|
||||
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for MaybeIds {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
match serde_json::Value::deserialize(deserializer)? {
|
||||
serde_json::Value::String(str) => {
|
||||
if str.len() <= MAX_STRING_SIZE {
|
||||
Ok(MaybeIds(sanitize_ids(
|
||||
str.split(",").map(|s| s.to_string()),
|
||||
)))
|
||||
} else {
|
||||
Err(serde::de::Error::custom("Given parameter is too long"))
|
||||
}
|
||||
}
|
||||
serde_json::Value::Array(vec) => {
|
||||
if vec.len() <= MAX_VECS {
|
||||
Ok(MaybeIds(sanitize_ids(
|
||||
vec.into_iter().map(|s| s.as_str().unwrap().to_string()),
|
||||
)))
|
||||
} else {
|
||||
Err(serde::de::Error::custom("Given parameter is too long"))
|
||||
}
|
||||
}
|
||||
_ => Err(serde::de::Error::custom("Bad ids format")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MaybeIds {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let s = self.0.join(",");
|
||||
write!(f, "{s}")
|
||||
}
|
||||
}
|
||||
|
||||
fn sanitize_ids(raw_ids: impl Iterator<Item = String>) -> Vec<String> {
|
||||
let mut results = Vec::new();
|
||||
raw_ids.for_each(|s| {
|
||||
let mut current = String::new();
|
||||
for c in s.to_lowercase().chars() {
|
||||
match c {
|
||||
' ' | ',' | '+' => {
|
||||
if !current.is_empty() {
|
||||
results.push(std::mem::take(&mut current));
|
||||
}
|
||||
}
|
||||
'-' => current.push('_'),
|
||||
c if c.is_alphanumeric() || c == '_' => current.push(c),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if !current.is_empty() {
|
||||
results.push(current);
|
||||
}
|
||||
});
|
||||
results
|
||||
}
|
||||
@@ -12,6 +12,7 @@ use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Index {
|
||||
#[schemars(description = "Date/day index")]
|
||||
DateIndex,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, sync::OnceLock};
|
||||
|
||||
use brk_computer::Computer;
|
||||
use brk_error::{Error, Result};
|
||||
@@ -10,13 +10,14 @@ use nucleo_matcher::{
|
||||
Config, Matcher,
|
||||
pattern::{AtomKind, CaseMatching, Normalization, Pattern},
|
||||
};
|
||||
use quick_cache::sync::Cache;
|
||||
use tabled::settings::Style;
|
||||
use vecdb::{AnyCollectableVec, AnyStoredVec};
|
||||
|
||||
mod deser;
|
||||
mod format;
|
||||
mod ids;
|
||||
mod index;
|
||||
mod maybe_ids;
|
||||
mod output;
|
||||
mod pagination;
|
||||
mod params;
|
||||
@@ -33,6 +34,11 @@ use vecs::Vecs;
|
||||
|
||||
use crate::vecs::{IdToVec, IndexToVec};
|
||||
|
||||
pub fn cached_errors() -> &'static Cache<String, String> {
|
||||
static CACHE: OnceLock<Cache<String, String>> = OnceLock::new();
|
||||
CACHE.get_or_init(|| Cache::new(1000))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Interface<'a> {
|
||||
vecs: Vecs<'a>,
|
||||
@@ -58,34 +64,31 @@ impl<'a> Interface<'a> {
|
||||
}
|
||||
|
||||
pub fn search(&self, params: &Params) -> Result<Vec<(String, &&dyn AnyCollectableVec)>> {
|
||||
let ids = ¶ms.ids;
|
||||
let index = params.index;
|
||||
|
||||
let ids_to_vec = self
|
||||
.vecs
|
||||
.index_to_id_to_vec
|
||||
.get(¶ms.index)
|
||||
.get(&index)
|
||||
.ok_or(Error::String(format!(
|
||||
"Index \"{}\" isn't a valid index",
|
||||
params.index
|
||||
index
|
||||
)))?;
|
||||
|
||||
let maybe_ids = params.ids.iter().flat_map(|s| {
|
||||
s.to_lowercase()
|
||||
.replace("-", "_")
|
||||
.split_whitespace()
|
||||
.flat_map(|s| {
|
||||
s.split(',')
|
||||
.flat_map(|s| s.split('+').map(|s| s.to_string()))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
maybe_ids
|
||||
ids.iter()
|
||||
.map(|id| {
|
||||
let vec = ids_to_vec.get(id.as_str()).ok_or_else(|| {
|
||||
let cached_errors = cached_errors();
|
||||
|
||||
if let Some(message) = cached_errors.get(id) {
|
||||
return Error::String(message)
|
||||
}
|
||||
|
||||
let mut message = format!(
|
||||
"No vec named \"{}\" indexed by \"{}\" found.\n",
|
||||
// tell if id found in another index
|
||||
id,
|
||||
params.index
|
||||
index
|
||||
);
|
||||
|
||||
let mut matcher = Matcher::new(Config::DEFAULT);
|
||||
@@ -111,9 +114,11 @@ impl<'a> Interface<'a> {
|
||||
message += &format!("\nBut there is a vec named {id} which supports the following indexes: {:#?}\n", index_to_vec.keys());
|
||||
}
|
||||
|
||||
cached_errors.insert(id.clone(), message.clone());
|
||||
|
||||
Error::String(message)
|
||||
});
|
||||
vec.map(|vec| (id, vec))
|
||||
vec.map(|vec| (id.clone(), vec))
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
use derive_deref::Deref;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deref, JsonSchema)]
|
||||
pub struct MaybeIds(Vec<String>);
|
||||
|
||||
impl From<String> for MaybeIds {
|
||||
fn from(value: String) -> Self {
|
||||
Self(vec![value])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Vec<&'a str>> for MaybeIds {
|
||||
fn from(value: Vec<&'a str>) -> Self {
|
||||
Self(value.iter().map(|s| s.to_string()).collect::<Vec<_>>())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for MaybeIds {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let maybe_ids = match serde_json::Value::deserialize(deserializer)? {
|
||||
serde_json::Value::String(str) => {
|
||||
str.split(",").map(|s| s.to_string()).collect::<Vec<_>>()
|
||||
}
|
||||
serde_json::Value::Array(vec) => vec
|
||||
.into_iter()
|
||||
.map(|s| s.as_str().unwrap().to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
_ => return Err(serde::de::Error::custom("Bad ids format")),
|
||||
};
|
||||
// dbg!(&maybe_ids);
|
||||
Ok(MaybeIds(maybe_ids))
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use tabled::Tabled as TabledTabled;
|
||||
use crate::Format;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(untagged)]
|
||||
#[serde(untagged, rename_all = "lowercase")]
|
||||
pub enum Output {
|
||||
Json(Value),
|
||||
CSV(String),
|
||||
|
||||
@@ -6,7 +6,7 @@ use serde::Deserialize;
|
||||
use crate::{
|
||||
Format, Index,
|
||||
deser::{de_unquote_i64, de_unquote_usize},
|
||||
maybe_ids::MaybeIds,
|
||||
ids::MaybeIds,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::path::Path;
|
||||
|
||||
use bitcoincore_rpc::{Auth, Client, Result};
|
||||
use brk_parser::Parser;
|
||||
use brk_parser::{BlockExtended, Parser};
|
||||
use brk_structs::Height;
|
||||
|
||||
#[allow(clippy::needless_doctest_main)]
|
||||
@@ -21,55 +21,26 @@ fn main() -> Result<()> {
|
||||
|
||||
let parser = Parser::new(bitcoin_dir.join("blocks"), Some(brk_dir), rpc);
|
||||
|
||||
let start = None;
|
||||
let end = None;
|
||||
parser
|
||||
.parse(start, end)
|
||||
.iter()
|
||||
.for_each(|(height, _block, hash)| {
|
||||
println!("{height}: {}", hash);
|
||||
});
|
||||
// let start = None;
|
||||
// let end = None;
|
||||
// parser
|
||||
// .parse(start, end)
|
||||
// .iter()
|
||||
// .for_each(|(height, _block, hash)| {
|
||||
// println!("{height}: {}", hash);
|
||||
// });
|
||||
|
||||
let block_0 = parser.get(Height::new(0));
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
block_0
|
||||
.txdata
|
||||
.first()
|
||||
.unwrap()
|
||||
.output
|
||||
.first()
|
||||
.unwrap()
|
||||
.script_pubkey
|
||||
);
|
||||
dbg!("{}", block_0.coinbase_tag());
|
||||
|
||||
let block_158251 = parser.get(Height::new(158251));
|
||||
println!(
|
||||
"{}",
|
||||
block_158251
|
||||
.txdata
|
||||
.first()
|
||||
.unwrap()
|
||||
.output
|
||||
.first()
|
||||
.unwrap()
|
||||
.script_pubkey
|
||||
);
|
||||
dbg!("{}", block_158251.coinbase_tag());
|
||||
|
||||
let block_173195 = parser.get(Height::new(173195));
|
||||
dbg!("{}", block_173195.coinbase_tag());
|
||||
|
||||
let block_840_000 = parser.get(Height::new(840_004));
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
block_840_000
|
||||
.txdata
|
||||
.first()
|
||||
.unwrap()
|
||||
.output
|
||||
.first()
|
||||
.unwrap()
|
||||
.value
|
||||
);
|
||||
dbg!("{}", block_840_000.coinbase_tag());
|
||||
|
||||
dbg!(i.elapsed());
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use bitcoin::Block;
|
||||
|
||||
pub trait BlockExtended {
|
||||
fn coinbase_tag(&self) -> String;
|
||||
fn coinbase_tag(&self) -> Cow<'_, str>;
|
||||
}
|
||||
|
||||
impl BlockExtended for Block {
|
||||
fn coinbase_tag(&self) -> String {
|
||||
let Some(input) = self.txdata.first().and_then(|tx| tx.input.first()) else {
|
||||
return String::new();
|
||||
};
|
||||
let bytes = input.script_sig.as_bytes();
|
||||
String::from_utf8_lossy(bytes)
|
||||
.chars()
|
||||
.filter(|&c| c != '\u{FFFD}' && (c >= ' ' || c == '\n' || c == '\r' || c == '\t'))
|
||||
.take(1_024)
|
||||
.collect()
|
||||
fn coinbase_tag(&self) -> Cow<'_, str> {
|
||||
String::from_utf8_lossy(
|
||||
self.txdata
|
||||
.first()
|
||||
.and_then(|tx| tx.input.first())
|
||||
.unwrap()
|
||||
.script_sig
|
||||
.as_bytes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ brk_parser = { workspace = true }
|
||||
vecdb = { workspace = true }
|
||||
jiff = { workspace = true }
|
||||
log = { workspace = true }
|
||||
quick_cache = "0.6.16"
|
||||
quick_cache = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tower-http = { version = "0.6.6", features = ["compression-full", "trace"] }
|
||||
|
||||
@@ -3,18 +3,11 @@ use brk_structs::{Height, Version};
|
||||
|
||||
pub trait AnyStore {
|
||||
fn commit(&mut self, height: Height) -> Result<()>;
|
||||
|
||||
fn persist(&self) -> Result<()>;
|
||||
|
||||
fn reset(&mut self) -> Result<()>;
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
fn height(&self) -> Option<Height>;
|
||||
|
||||
fn has(&self, height: Height) -> bool;
|
||||
|
||||
fn needs(&self, height: Height) -> bool;
|
||||
|
||||
fn version(&self) -> Version;
|
||||
}
|
||||
|
||||
@@ -126,12 +126,12 @@ where
|
||||
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v)))))
|
||||
// }
|
||||
|
||||
// pub fn tx_iter(&self) -> impl Iterator<Item = (K, V)> {
|
||||
// self.rtx
|
||||
// .iter(&self.partition.load())
|
||||
// .map(|res| res.unwrap())
|
||||
// .map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
|
||||
// }
|
||||
pub fn iter(&self) -> impl Iterator<Item = (K, V)> {
|
||||
self.rtx
|
||||
.iter(self.partition.as_ref().unwrap())
|
||||
.map(|res| res.unwrap())
|
||||
.map(|(k, v)| (K::from(ByteView::from(k)), V::from(ByteView::from(v))))
|
||||
}
|
||||
|
||||
pub fn insert_if_needed(&mut self, key: K, value: V, height: Height) {
|
||||
if self.needs(height) {
|
||||
|
||||
@@ -10,6 +10,8 @@ rust-version.workspace = true
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
allocative = { workspace = true }
|
||||
allocative_derive = { workspace = true }
|
||||
bitcoin = { workspace = true }
|
||||
bitcoincore-rpc = { workspace = true }
|
||||
brk_error = {workspace = true}
|
||||
|
||||
@@ -25,6 +25,25 @@ pub enum AddressBytes {
|
||||
P2A(P2ABytes),
|
||||
}
|
||||
|
||||
impl fmt::Display for AddressBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
AddressBytes::P2PK65(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2PK33(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2PKH(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2SH(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2WPKH(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2WSH(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2TR(bytes) => bytes.to_string(),
|
||||
AddressBytes::P2A(bytes) => bytes.to_string(),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddressBytes {
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
match self {
|
||||
|
||||
@@ -44,6 +44,7 @@ impl Serialize for AnyAddressIndex {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum AnyAddressDataIndexEnum {
|
||||
Loaded(LoadedAddressIndex),
|
||||
Empty(EmptyAddressIndex),
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div, Mul},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -20,6 +21,7 @@ use super::{Sats, StoredF64};
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct Bitcoin(f64);
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ use std::{
|
||||
ops::{Add, Rem},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use brk_error::Error;
|
||||
use vecdb::{CheckedSub, FromCoarserIndex, Printable, StoredCompressed};
|
||||
use jiff::Span;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, FromCoarserIndex, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, WeekIndex, YearIndex};
|
||||
@@ -28,6 +29,7 @@ use super::Date;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct DateIndex(u16);
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::{Date, DateIndex, YearIndex};
|
||||
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, YearIndex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct DecadeIndex(u16);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -25,6 +26,7 @@ use super::Height;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct DifficultyEpoch(u16);
|
||||
|
||||
|
||||
@@ -4,11 +4,14 @@ use std::{
|
||||
ops::{Add, AddAssign, Div, Mul},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{Low, Open};
|
||||
|
||||
use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64};
|
||||
|
||||
#[derive(
|
||||
@@ -24,6 +27,7 @@ use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64};
|
||||
Serialize,
|
||||
Deserialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct Dollars(f64);
|
||||
|
||||
@@ -78,8 +82,8 @@ impl From<Dollars> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Close<Dollars>> for Dollars {
|
||||
fn from(value: Close<Dollars>) -> Self {
|
||||
impl From<Open<Dollars>> for Dollars {
|
||||
fn from(value: Open<Dollars>) -> Self {
|
||||
Self(value.0)
|
||||
}
|
||||
}
|
||||
@@ -90,6 +94,18 @@ impl From<High<Dollars>> for Dollars {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Low<Dollars>> for Dollars {
|
||||
fn from(value: Low<Dollars>) -> Self {
|
||||
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)
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::Serialize;
|
||||
use vecdb::StoredCompressed;
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -10,7 +11,16 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
use super::{Sats, StoredU64};
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout, StoredCompressed,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Serialize,
|
||||
FromBytes,
|
||||
Immutable,
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct FeeRate(f64);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -25,6 +26,7 @@ use super::Height;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct HalvingEpoch(u16);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Rem},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use bitcoincore_rpc::{Client, RpcApi};
|
||||
use byteview::ByteView;
|
||||
use derive_deref::Deref;
|
||||
@@ -32,6 +33,7 @@ use super::StoredU64;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct Height(u32);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
@@ -24,6 +25,7 @@ use super::Vin;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct InputIndex(u64);
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use super::{Date, DateIndex, YearIndex};
|
||||
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, YearIndex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct MonthIndex(u16);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::{Serialize, Serializer, ser::SerializeTuple};
|
||||
use vecdb::StoredCompressed;
|
||||
@@ -473,6 +474,7 @@ where
|
||||
DerefMut,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct Close<T>(T);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
@@ -26,6 +27,7 @@ use super::Vout;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct OutputIndex(u64);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[repr(u8)]
|
||||
pub enum OutputType {
|
||||
P2PK65,
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -25,6 +26,7 @@ use super::MonthIndex;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct QuarterIndex(u16);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div, Mul, SubAssign},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use bitcoin::Amount;
|
||||
use derive_deref::Deref;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -30,6 +31,7 @@ use super::{Bitcoin, Cents, Dollars, Height};
|
||||
Serialize,
|
||||
Deserialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct Sats(u64);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -25,6 +26,7 @@ use super::MonthIndex;
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct SemesterIndex(u16);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::{Printable, StoredCompressed};
|
||||
@@ -19,6 +20,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct StoredBool(u16);
|
||||
|
||||
|
||||
@@ -6,11 +6,14 @@ use std::{
|
||||
ops::{Add, AddAssign, Div, Mul, Sub},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{Close, StoredU32};
|
||||
|
||||
use super::{Dollars, StoredF64};
|
||||
|
||||
#[derive(
|
||||
@@ -25,6 +28,7 @@ use super::{Dollars, StoredF64};
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct StoredF32(f32);
|
||||
|
||||
@@ -65,12 +69,24 @@ impl From<usize> for StoredF32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredU32> for StoredF32 {
|
||||
fn from(value: StoredU32) -> Self {
|
||||
Self(f32::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<StoredF32> for StoredF32 {
|
||||
fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
Some(Self(self.0 - rhs.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<usize> for StoredF32 {
|
||||
fn checked_sub(self, rhs: usize) -> Option<Self> {
|
||||
Some(Self(self.0 - rhs as f32))
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
@@ -78,6 +94,13 @@ impl Div<usize> for StoredF32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<StoredU32> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: StoredU32) -> Self::Output {
|
||||
Self(self.0 / f32::from(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredF32 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
@@ -103,6 +126,12 @@ impl From<Dollars> for StoredF32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Close<Dollars>> for StoredF32 {
|
||||
fn from(value: Close<Dollars>) -> Self {
|
||||
Self::from(*value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Dollars> for StoredF32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Dollars) -> Self::Output {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
f64,
|
||||
iter::Sum,
|
||||
ops::{Add, AddAssign, Div, Mul},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
@@ -23,6 +25,7 @@ use crate::{Bitcoin, Dollars};
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct StoredF64(f64);
|
||||
|
||||
@@ -75,6 +78,13 @@ impl Div<StoredF64> for StoredF64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Dollars> for StoredF64 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Dollars) -> Self::Output {
|
||||
Self::from(self.0 / *rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredF64 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
@@ -159,3 +169,9 @@ impl Printable for StoredF64 {
|
||||
&["f64"]
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for StoredF64 {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
Self(iter.map(|v| v.0).sum::<f64>())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use byteview::ByteView;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
@@ -26,6 +28,12 @@ impl From<String> for StoredString {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Cow<'_, str>> for StoredString {
|
||||
fn from(value: Cow<'_, str>) -> Self {
|
||||
Self(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ByteView> for StoredString {
|
||||
fn from(value: ByteView) -> Self {
|
||||
let bytes = &*value;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign, Div};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
@@ -27,11 +28,13 @@ use super::{
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct StoredU16(u16);
|
||||
|
||||
impl StoredU16 {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const ONE: Self = Self(1);
|
||||
|
||||
pub fn new(v: u16) -> Self {
|
||||
Self(v)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign, Div};
|
||||
use std::ops::{Add, AddAssign, Div, Mul};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
@@ -27,15 +28,21 @@ use super::{
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct StoredU32(u32);
|
||||
|
||||
impl StoredU32 {
|
||||
pub const ZERO: Self = Self(0);
|
||||
pub const ONE: Self = Self(1);
|
||||
|
||||
pub fn new(counter: u32) -> Self {
|
||||
Self(counter)
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.0 == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for StoredU32 {
|
||||
@@ -44,6 +51,12 @@ impl From<u32> for StoredU32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredU32> for f32 {
|
||||
fn from(value: StoredU32) -> Self {
|
||||
value.0 as f32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for StoredU32 {
|
||||
fn from(value: usize) -> Self {
|
||||
if value > u32::MAX as usize {
|
||||
@@ -59,6 +72,15 @@ impl CheckedSub<StoredU32> for StoredU32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl CheckedSub<usize> for StoredU32 {
|
||||
fn checked_sub(self, rhs: usize) -> Option<Self> {
|
||||
if rhs > u32::MAX as usize {
|
||||
panic!()
|
||||
}
|
||||
self.0.checked_sub(rhs as u32).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for StoredU32 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
@@ -79,6 +101,17 @@ impl AddAssign for StoredU32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<usize> for StoredU32 {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: usize) -> Self::Output {
|
||||
let res = self.0 as usize * rhs;
|
||||
if res > u32::MAX as usize {
|
||||
panic!()
|
||||
}
|
||||
Self::from(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for StoredU32 {
|
||||
fn from(value: f64) -> Self {
|
||||
if value < 0.0 || value > u32::MAX as f64 {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign, Div};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
@@ -28,6 +29,7 @@ use super::{
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct StoredU64(u64);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign, Div};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use jiff::{civil::date, tz::TimeZone};
|
||||
use serde::Serialize;
|
||||
@@ -23,6 +24,7 @@ use super::Date;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct Timestamp(u32);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
use allocative::Allocative;
|
||||
use byteview::ByteView;
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::Serialize;
|
||||
@@ -27,6 +28,7 @@ use super::StoredU32;
|
||||
KnownLayout,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct TxIndex(u32);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -25,6 +26,7 @@ use super::{Date, DateIndex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct WeekIndex(u16);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::ops::{Add, AddAssign, Div};
|
||||
|
||||
use allocative::Allocative;
|
||||
use derive_deref::Deref;
|
||||
use serde::Serialize;
|
||||
use vecdb::StoredCompressed;
|
||||
@@ -20,6 +21,7 @@ use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
FromBytes,
|
||||
Serialize,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct Weight(u64);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{
|
||||
ops::{Add, AddAssign, Div},
|
||||
};
|
||||
|
||||
use allocative::Allocative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{CheckedSub, Printable, StoredCompressed};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
@@ -25,6 +26,7 @@ use super::{Date, DateIndex, MonthIndex};
|
||||
IntoBytes,
|
||||
KnownLayout,
|
||||
StoredCompressed,
|
||||
Allocative,
|
||||
)]
|
||||
pub struct YearIndex(u16);
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "1.89.0"
|
||||
@@ -572,6 +572,7 @@
|
||||
|
||||
&:has(input:checked) {
|
||||
color: var(--color);
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[data-screenshot="true"] &:has(input:not(:checked)) {
|
||||
@@ -950,6 +951,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
/*font-style: italic;*/
|
||||
|
||||
> legend,
|
||||
> div {
|
||||
@@ -1051,6 +1053,7 @@
|
||||
|
||||
&:has(input:not(:checked)) {
|
||||
color: var(--off-color);
|
||||
/*font-style: italic;*/
|
||||
|
||||
> span.main > span.name {
|
||||
text-decoration-thickness: 1.5px;
|
||||
@@ -1263,7 +1266,7 @@
|
||||
}
|
||||
|
||||
td {
|
||||
text-transform: lowercase;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
@@ -367,7 +367,7 @@ export function init({
|
||||
case null:
|
||||
case CANDLE: {
|
||||
series = chart.addCandlestickSeries({
|
||||
vecId: "ohlc_in_sats",
|
||||
vecId: "price_ohlc_in_sats",
|
||||
name: "Price",
|
||||
unit: topUnit,
|
||||
inverse: true,
|
||||
@@ -378,7 +378,7 @@ export function init({
|
||||
}
|
||||
case LINE: {
|
||||
series = chart.addLineSeries({
|
||||
vecId: "close_in_sats",
|
||||
vecId: "price_close_in_sats",
|
||||
name: "Price",
|
||||
unit: topUnit,
|
||||
color: colors.default,
|
||||
|
||||
+556
-536
File diff suppressed because it is too large
Load Diff
+533
-224
File diff suppressed because it is too large
Load Diff
@@ -515,12 +515,17 @@ function createIndexToVecIds(vecIdToIndexes) {
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {number | OHLCTuple} args.value
|
||||
* @param {number | string | Object | Array<any>} args.value
|
||||
* @param {Unit} args.unit
|
||||
*/
|
||||
function serializeValue({ value, unit }) {
|
||||
if (typeof value !== "number") {
|
||||
return JSON.stringify(value);
|
||||
const t = typeof value;
|
||||
if (value === null) {
|
||||
return "null";
|
||||
} else if (typeof value === "string") {
|
||||
return value;
|
||||
} else if (t !== "number") {
|
||||
return JSON.stringify(value).replaceAll('"', "").slice(1, -1);
|
||||
} else if (value !== 18446744073709552000) {
|
||||
if (unit === "USD" || unit === "Difficulty" || unit === "sat/vB") {
|
||||
return value.toLocaleString("en-us", {
|
||||
|
||||
Reference in New Issue
Block a user