From 62d6333e5c6de0495166ebb6559cf6f0e4314194 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Mon, 6 May 2024 08:55:27 -0400 Subject: [PATCH 1/9] fix: Repair --- src/lib.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7555ba3..b2f9e38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,9 +72,23 @@ impl HypersyncClient { } async fn stream_impl(&self, query: Query, config: StreamConfig) -> Result { - let query = query.try_convert().context("parse query")?; + let mut query = query.try_convert().context("parse query")?; let config = config.try_convert().context("parse config")?; + // 0x0000... is a special address that means no address + query.logs = query + .logs + .into_iter() + .map(|log| { + let mut log = log; + let address = log.address.clone(); + if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + log.address = vec![]; + } + log + }) + .collect(); + let rx = self .inner .stream::(query, config) @@ -105,9 +119,23 @@ impl HypersyncClient { } async fn stream_events_impl(&self, query: Query, config: StreamConfig) -> Result { - let query = query.try_convert().context("parse query")?; + let mut query = query.try_convert().context("parse query")?; let config = config.try_convert().context("parse config")?; + // 0x0000... is a special address that means no address + query.logs = query + .logs + .into_iter() + .map(|log| { + let mut log = log; + let address = log.address.clone(); + if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + log.address = vec![]; + } + log + }) + .collect(); + let rx = self .inner .stream::(query, config) @@ -134,9 +162,23 @@ impl HypersyncClient { } async fn create_parquet_folder_impl(&self, query: Query, config: ParquetConfig) -> Result<()> { - let query = query.try_convert().context("parse query")?; + let mut query = query.try_convert().context("parse query")?; let config = config.try_convert().context("parse parquet config")?; + // 0x0000... is a special address that means no address + query.logs = query + .logs + .into_iter() + .map(|log| { + let mut log = log; + let address = log.address.clone(); + if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + log.address = vec![]; + } + log + }) + .collect(); + self.inner .create_parquet_folder(query, config) .await @@ -156,7 +198,21 @@ impl HypersyncClient { } async fn send_req_impl(&self, query: Query) -> Result { - let query = query.try_convert().context("parse query")?; + let mut query = query.try_convert().context("parse query")?; + + // 0x0000... is a special address that means no address + query.logs = query + .logs + .into_iter() + .map(|log| { + let mut log = log; + let address = log.address.clone(); + if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + log.address = vec![]; + } + log + }) + .collect(); let res = self .inner @@ -202,6 +258,20 @@ impl HypersyncClient { } } + // 0x0000... is a special address that means no address + query.logs = query + .logs + .into_iter() + .map(|log| { + let mut log = log; + let address = log.address.clone(); + if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + log.address = vec![]; + } + log + }) + .collect(); + let res = self .inner .send::(&query) From 7a22f646280f755eb91035b97650ac7fbe1ffba7 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Mon, 6 May 2024 18:33:09 -0400 Subject: [PATCH 2/9] fix: More work to make wildcard addresses work. Includes a patch to skar-client --- Cargo.toml | 6 + patch/skar-client-0.16.3/.cargo-ok | 1 + patch/skar-client-0.16.3/.cargo_vcs_info.json | 6 + patch/skar-client-0.16.3/Cargo.toml | 133 +++ patch/skar-client-0.16.3/Cargo.toml.orig | 58 ++ .../skar-client-0.16.3/src/column_mapping.rs | 206 +++++ patch/skar-client-0.16.3/src/config.rs | 18 + patch/skar-client-0.16.3/src/decode.rs | 159 ++++ patch/skar-client-0.16.3/src/lib.rs | 465 +++++++++++ patch/skar-client-0.16.3/src/parquet_out.rs | 783 ++++++++++++++++++ patch/skar-client-0.16.3/src/rayon_async.rs | 16 + .../src/transport_format.rs | 39 + patch/skar-client-0.16.3/src/types.rs | 104 +++ .../test-data/ens_token_abi.json | 1 + .../test-data/erc20.abi.json | 222 +++++ .../test-data/nameless.abi.json | 1 + patch/skar-client-0.16.3/tests/api_test.rs | 394 +++++++++ src/decode.rs | 14 +- src/lib.rs | 10 +- 19 files changed, 2618 insertions(+), 18 deletions(-) create mode 100644 patch/skar-client-0.16.3/.cargo-ok create mode 100644 patch/skar-client-0.16.3/.cargo_vcs_info.json create mode 100644 patch/skar-client-0.16.3/Cargo.toml create mode 100644 patch/skar-client-0.16.3/Cargo.toml.orig create mode 100644 patch/skar-client-0.16.3/src/column_mapping.rs create mode 100644 patch/skar-client-0.16.3/src/config.rs create mode 100644 patch/skar-client-0.16.3/src/decode.rs create mode 100644 patch/skar-client-0.16.3/src/lib.rs create mode 100644 patch/skar-client-0.16.3/src/parquet_out.rs create mode 100644 patch/skar-client-0.16.3/src/rayon_async.rs create mode 100644 patch/skar-client-0.16.3/src/transport_format.rs create mode 100644 patch/skar-client-0.16.3/src/types.rs create mode 100644 patch/skar-client-0.16.3/test-data/ens_token_abi.json create mode 100644 patch/skar-client-0.16.3/test-data/erc20.abi.json create mode 100644 patch/skar-client-0.16.3/test-data/nameless.abi.json create mode 100644 patch/skar-client-0.16.3/tests/api_test.rs diff --git a/Cargo.toml b/Cargo.toml index 8c0b9a9..8b60e24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,12 @@ version = "0.0.0" [lib] crate-type = ["cdylib"] +[package.metadata.patch] +crates = ["skar-client"] + +[patch.crates-io] +skar-client = { path="./patch/skar-client-0.16.3" } + [dependencies] # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix napi = { version = "2", default-features = false, features = [ diff --git a/patch/skar-client-0.16.3/.cargo-ok b/patch/skar-client-0.16.3/.cargo-ok new file mode 100644 index 0000000..5f8b795 --- /dev/null +++ b/patch/skar-client-0.16.3/.cargo-ok @@ -0,0 +1 @@ +{"v":1} \ No newline at end of file diff --git a/patch/skar-client-0.16.3/.cargo_vcs_info.json b/patch/skar-client-0.16.3/.cargo_vcs_info.json new file mode 100644 index 0000000..d2a9589 --- /dev/null +++ b/patch/skar-client-0.16.3/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "598b49bbf4fe44008a0728847b147f21a35ff1e5" + }, + "path_in_vcs": "skar-client" +} \ No newline at end of file diff --git a/patch/skar-client-0.16.3/Cargo.toml b/patch/skar-client-0.16.3/Cargo.toml new file mode 100644 index 0000000..0f62fc2 --- /dev/null +++ b/patch/skar-client-0.16.3/Cargo.toml @@ -0,0 +1,133 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "skar-client" +version = "0.16.3" +description = "client library for skar" +license = "MIT" + +[dependencies.alloy-dyn-abi] +version = "0.6" + +[dependencies.alloy-json-abi] +version = "0.6" + +[dependencies.anyhow] +version = "1" + +[dependencies.arrayvec] +version = "0.7" +features = ["serde"] + +[dependencies.arrow2] +version = "0.18" +features = [ + "io_json", + "io_ipc", + "io_ipc_compression", + "io_parquet_zstd", + "io_parquet_lz4", + "io_parquet", + "compute_cast", +] + +[dependencies.capnp] +version = "0.19" + +[dependencies.faster-hex] +version = "0.9" + +[dependencies.fastrange-rs] +version = "0.1" + +[dependencies.futures] +version = "0.3" + +[dependencies.log] +version = "0.4" + +[dependencies.num_cpus] +version = "1" + +[dependencies.parquet2] +version = "0.17" +features = ["async"] + +[dependencies.rand] +version = "0.8" + +[dependencies.rayon] +version = "1" + +[dependencies.reqwest] +version = "0.11" +features = [ + "json", + "rustls-tls", +] +default-features = false + +[dependencies.ruint] +version = "1" + +[dependencies.serde] +version = "1" +features = ["derive"] + +[dependencies.serde_json] +version = "1" + +[dependencies.skar-format] +version = "0.2.0" + +[dependencies.skar-net-types] +version = "0.2.0" + +[dependencies.skar-schema] +version = "0.1.0" + +[dependencies.tokio] +version = "1" +features = [ + "rt-multi-thread", + "fs", + "test-util", + "rt", + "macros", +] +default-features = false + +[dependencies.tokio-util] +version = "0.7.10" +features = ["compat"] + +[dependencies.url] +version = "2" +features = ["serde"] + +[dependencies.xxhash-rust] +version = "0.8" +features = ["xxh3"] + +[dev-dependencies.env_logger] +version = "0.11" + +[dev-dependencies.hex-literal] +version = "0.4" + +[dev-dependencies.maplit] +version = "1" + +[dev-dependencies.uuid] +version = "1" +features = ["v4"] diff --git a/patch/skar-client-0.16.3/Cargo.toml.orig b/patch/skar-client-0.16.3/Cargo.toml.orig new file mode 100644 index 0000000..372cf27 --- /dev/null +++ b/patch/skar-client-0.16.3/Cargo.toml.orig @@ -0,0 +1,58 @@ +[package] +name = "skar-client" +version = "0.16.3" +edition = "2021" +description = "client library for skar" +license = "MIT" + +[dependencies] +anyhow = "1" +url = { version = "2", features = ["serde"] } +arrow2 = { version = "0.18", features = [ + "io_json", + "io_ipc", + "io_ipc_compression", + "io_parquet_zstd", + "io_parquet_lz4", + "io_parquet", + "compute_cast", +] } +parquet2 = { version = "0.17", features = ["async"] } +serde_json = "1" +capnp = "0.19" +serde = { version = "1", features = ["derive"] } +futures = "0.3" +arrayvec = { version = "0.7", features = ["serde"] } +tokio = { version = "1", default-features = false, features = [ + "rt-multi-thread", + "fs", + "test-util", + "rt", + "macros", +] } +log = "0.4" +fastrange-rs = "0.1" +rand = "0.8" +tokio-util = { version = "0.7.10", features = ["compat"] } +alloy-dyn-abi = "0.6" +alloy-json-abi = "0.6" +xxhash-rust = { version = "0.8", features = ["xxh3"] } +num_cpus = "1" +rayon = "1" +faster-hex = "0.9" +ruint = "1" + +skar-net-types = { path = "../net-types", version = "0.2.0" } +skar-format = { path = "../format", version = "0.2.0" } +skar-schema = { path = "../schema", version = "0.1.0" } + +[dependencies.reqwest] +version = "0.11" +default-features = false +features = ["json", "rustls-tls"] + +[dev-dependencies] +maplit = "1" +hex-literal = "0.4" +uuid = { version = "1", features = ["v4"] } +env_logger = "0.11" diff --git a/patch/skar-client-0.16.3/src/column_mapping.rs b/patch/skar-client-0.16.3/src/column_mapping.rs new file mode 100644 index 0000000..d12da0f --- /dev/null +++ b/patch/skar-client-0.16.3/src/column_mapping.rs @@ -0,0 +1,206 @@ +use std::collections::BTreeMap; + +use anyhow::{anyhow, Context, Result}; +use arrow2::array::{ + Array, BinaryArray, Float32Array, Float64Array, Int32Array, Int64Array, MutablePrimitiveArray, + PrimitiveArray, UInt32Array, UInt64Array, +}; +use arrow2::compute::cast; +use arrow2::datatypes::{DataType as ArrowDataType, Field, Schema}; +use arrow2::types::NativeType; +use rayon::prelude::*; +use ruint::aliases::U256; +use serde::{Deserialize, Serialize}; +use skar_schema::ArrowChunk; + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct ColumnMapping { + #[serde(default)] + pub block: BTreeMap, + #[serde(default)] + pub transaction: BTreeMap, + #[serde(default)] + pub log: BTreeMap, + #[serde(default)] + pub trace: BTreeMap, + #[serde(default)] + pub decoded_log: BTreeMap, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum DataType { + Float64, + Float32, + UInt64, + UInt32, + Int64, + Int32, +} + +impl From for ArrowDataType { + fn from(value: DataType) -> Self { + match value { + DataType::Float64 => Self::Float64, + DataType::Float32 => Self::Float32, + DataType::UInt64 => Self::UInt64, + DataType::UInt32 => Self::UInt32, + DataType::Int64 => Self::Int64, + DataType::Int32 => Self::Int32, + } + } +} + +pub fn apply_to_chunk( + chunk: &ArrowChunk, + field_names: &[&str], + mapping: &BTreeMap, +) -> Result { + if mapping.is_empty() { + return Ok(chunk.clone()); + } + + let columns = chunk + .columns() + .par_iter() + .zip(field_names.par_iter()) + .map(|(col, &field_name)| { + let col = match mapping.get(field_name) { + Some(&dt) => map_column(&**col, dt) + .context(format!("apply cast to colum '{}'", field_name))?, + None => col.clone(), + }; + + Ok(col) + }) + .collect::>>()?; + + Ok(ArrowChunk::new(columns)) +} + +/// Warning: This function does not validate the mapping types! +/// So same mapping might fail if applied to actual data even if this function maps the schema normally. +pub fn apply_to_schema(schema: &Schema, mapping: &BTreeMap) -> Result { + let fields = schema + .fields + .iter() + .map(|field| match mapping.get(&field.name) { + Some(&dt) => Field::new(&field.name, dt.into(), field.is_nullable), + None => field.clone(), + }) + .collect::>(); + + Ok(Schema::from(fields)) +} + +pub fn map_column(col: &dyn Array, target_data_type: DataType) -> Result> { + fn to_box(arr: T) -> Box { + Box::new(arr) + } + + match target_data_type { + DataType::Float64 => map_to_f64(col).map(to_box), + DataType::Float32 => map_to_f32(col).map(to_box), + DataType::UInt64 => map_to_uint64(col).map(to_box), + DataType::UInt32 => map_to_uint32(col).map(to_box), + DataType::Int64 => map_to_int64(col).map(to_box), + DataType::Int32 => map_to_int32(col).map(to_box), + } +} + +fn map_to_f64(col: &dyn Array) -> Result { + match col.data_type() { + &ArrowDataType::Binary => { + binary_to_target_array(col.as_any().downcast_ref::>().unwrap()) + } + &ArrowDataType::UInt64 => Ok(cast::primitive_as_primitive( + col.as_any().downcast_ref::().unwrap(), + &ArrowDataType::Float64, + )), + dt => Err(anyhow!("Can't convert {:?} to f64", dt)), + } +} + +fn map_to_f32(col: &dyn Array) -> Result { + match col.data_type() { + &ArrowDataType::Binary => { + binary_to_target_array(col.as_any().downcast_ref::>().unwrap()) + } + &ArrowDataType::UInt64 => Ok(cast::primitive_as_primitive( + col.as_any().downcast_ref::().unwrap(), + &ArrowDataType::Float32, + )), + dt => Err(anyhow!("Can't convert {:?} to f32", dt)), + } +} + +fn map_to_uint64(col: &dyn Array) -> Result { + match col.data_type() { + &ArrowDataType::Binary => { + binary_to_target_array(col.as_any().downcast_ref::>().unwrap()) + } + &ArrowDataType::UInt64 => Ok(cast::primitive_as_primitive( + col.as_any().downcast_ref::().unwrap(), + &ArrowDataType::UInt64, + )), + dt => Err(anyhow!("Can't convert {:?} to uint64", dt)), + } +} + +fn map_to_uint32(col: &dyn Array) -> Result { + match col.data_type() { + &ArrowDataType::Binary => { + binary_to_target_array(col.as_any().downcast_ref::>().unwrap()) + } + &ArrowDataType::UInt64 => Ok(cast::primitive_as_primitive( + col.as_any().downcast_ref::().unwrap(), + &ArrowDataType::UInt32, + )), + dt => Err(anyhow!("Can't convert {:?} to uint32", dt)), + } +} + +fn map_to_int64(col: &dyn Array) -> Result { + match col.data_type() { + &ArrowDataType::Binary => { + binary_to_target_array(col.as_any().downcast_ref::>().unwrap()) + } + &ArrowDataType::UInt64 => Ok(cast::primitive_as_primitive( + col.as_any().downcast_ref::().unwrap(), + &ArrowDataType::Int64, + )), + dt => Err(anyhow!("Can't convert {:?} to int64", dt)), + } +} + +fn map_to_int32(col: &dyn Array) -> Result { + match col.data_type() { + &ArrowDataType::Binary => { + binary_to_target_array(col.as_any().downcast_ref::>().unwrap()) + } + &ArrowDataType::UInt64 => Ok(cast::primitive_as_primitive( + col.as_any().downcast_ref::().unwrap(), + &ArrowDataType::Int32, + )), + dt => Err(anyhow!("Can't convert {:?} to int32", dt)), + } +} + +fn binary_to_target_array>( + src: &BinaryArray, +) -> Result> { + let mut out = MutablePrimitiveArray::with_capacity(src.len()); + + for val in src.iter() { + out.push(val.map(binary_to_target).transpose()?); + } + + Ok(out.into()) +} + +fn binary_to_target>(src: &[u8]) -> Result { + let big_num = U256::from_be_slice(src); + big_num + .try_into() + .map_err(|_e| anyhow!("failed to cast number to requested type")) +} diff --git a/patch/skar-client-0.16.3/src/config.rs b/patch/skar-client-0.16.3/src/config.rs new file mode 100644 index 0000000..b79c00e --- /dev/null +++ b/patch/skar-client-0.16.3/src/config.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Serialize}; +use std::num::NonZeroU64; +use url::Url; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct Config { + /// Url of the source hypersync instance + pub url: Url, + /// Optional bearer_token to put into http requests made to source hypersync instance + pub bearer_token: Option, + /// Timout treshold for a single http request in milliseconds, default is 30 seconds (30_000ms) + #[serde(default = "default_http_req_timeout_millis")] + pub http_req_timeout_millis: NonZeroU64, +} + +pub fn default_http_req_timeout_millis() -> NonZeroU64 { + NonZeroU64::new(30000).unwrap() +} diff --git a/patch/skar-client-0.16.3/src/decode.rs b/patch/skar-client-0.16.3/src/decode.rs new file mode 100644 index 0000000..58f6b1c --- /dev/null +++ b/patch/skar-client-0.16.3/src/decode.rs @@ -0,0 +1,159 @@ +use std::collections::HashMap as StdHashMap; + +use alloy_dyn_abi::{DecodedEvent, DynSolEvent, DynSolType, ResolveSolEvent}; +use alloy_json_abi::JsonAbi; +use anyhow::{Context, Result}; +use arrow2::array::BinaryArray; +use xxhash_rust::xxh3::Xxh3Builder; + +use crate::ArrowBatch; + +pub type FastMap = StdHashMap; + +pub struct Decoder { + contracts: FastMap, FastMap, DynSolEvent>>, +} + +impl Decoder { + pub fn new(json_abis: &[(skar_format::Address, JsonAbi)]) -> Result { + let mut contracts = FastMap::default(); + + for (addr, abi) in json_abis.iter() { + let mut event_map = FastMap::default(); + + for (_, events) in abi.events.iter() { + for event in events { + event_map.insert( + event.selector().to_vec(), + event.resolve().context("resolve event")?, + ); + } + } + + contracts.insert(addr.to_vec(), event_map.clone()); + } + + Ok(Self { contracts }) + } + + #[inline] + pub fn decode( + &self, + address: &[u8], + topic0: &[u8], + topics: &[Option<&[u8]>], + data: &[u8], + ) -> Result> { + let event = match self.contracts.get(address) { + Some(contract) => match contract.get(topic0) { + Some(event) => event, + None => { + if let Some(event) = self.contracts.iter().find_map(|(address, contract)| { + if (*address).as_slice()[0..19] == [0u8; 19] { + contract.get(topic0) + } else { + None + } + }) { + event + } else { + return Ok(None); + } + } + }, + None => { + if let Some(event) = self.contracts.iter().find_map(|(address, contract)| { + if (*address).as_slice()[0..19] == [0u8; 19] { + contract.get(topic0) + } else { + None + } + }) { + event + } else { + return Ok(None); + } + } + }; + + let topics = topics + .iter() + .filter_map(|&t| t.map(|t| t.try_into().unwrap())); + + // Check if we are decoding a single u256 and the body is empty + // + // This case can happen when decoding zero value erc20 transfers + let decoded = if data.is_empty() && event.body() == [DynSolType::Uint(256)] { + event + .decode_log_parts(topics, [0; 32].as_slice(), false) + .context("decode log parts")? + } else { + event + .decode_log_parts(topics, data, false) + .context("decode log parts")? + }; + + Ok(Some(decoded)) + } + + pub fn decode_logs(&self, logs: &[ArrowBatch]) -> Result>>> { + let mut events = Vec::new(); + + for batch in logs { + let address = match batch.column::>("address") { + Ok(address) => address, + Err(_) => return Ok(None), + }; + let data = match batch.column::>("data") { + Ok(data) => data, + Err(_) => return Ok(None), + }; + let topic0 = match batch.column::>("topic0") { + Ok(topic0) => topic0, + Err(_) => return Ok(None), + }; + let topic1 = match batch.column::>("topic1") { + Ok(topic1) => topic1, + Err(_) => return Ok(None), + }; + let topic2 = match batch.column::>("topic2") { + Ok(topic2) => topic2, + Err(_) => return Ok(None), + }; + let topic3 = match batch.column::>("topic3") { + Ok(topic3) => topic3, + Err(_) => return Ok(None), + }; + + for (((((address, data), topic0), topic1), topic2), topic3) in address + .values_iter() + .zip(data.values_iter()) + .zip(topic0.iter()) + .zip(topic1.iter()) + .zip(topic2.iter()) + .zip(topic3.iter()) + { + let topic0 = match topic0 { + Some(topic0) => topic0, + None => { + events.push(None); + continue; + } + }; + + let decoded = self + .decode( + address, + topic0, + &[Some(topic0), topic1, topic2, topic3], + data, + ) + .context("decode event")?; + + events.push(decoded); + } + } + + Ok(Some(events)) + } +} diff --git a/patch/skar-client-0.16.3/src/lib.rs b/patch/skar-client-0.16.3/src/lib.rs new file mode 100644 index 0000000..9f18abb --- /dev/null +++ b/patch/skar-client-0.16.3/src/lib.rs @@ -0,0 +1,465 @@ +use std::{cmp, collections::BTreeSet, error::Error, time::Duration}; + +use anyhow::{anyhow, Context, Result}; +use arrayvec::ArrayVec; +use arrow2::{array::Array, chunk::Chunk}; +use format::{Address, LogArgument}; +use futures::StreamExt; +use reqwest::Method; +use skar_net_types::{ + skar_net_types_capnp, ArchiveHeight, FieldSelection, LogSelection, Query, RollbackGuard, + TransactionSelection, +}; + +mod column_mapping; +pub mod config; +mod decode; +mod parquet_out; +mod rayon_async; +mod transport_format; +mod types; + +pub use column_mapping::{ColumnMapping, DataType}; +pub use config::Config; +pub use decode::Decoder; +pub use skar_format as format; +use tokio::sync::mpsc; +pub use transport_format::{ArrowIpc, TransportFormat}; +pub use types::{ArrowBatch, ParquetConfig, QueryResponse, QueryResponseData, StreamConfig}; + +pub type ArrowChunk = Chunk>; + +#[derive(Clone)] +pub struct Client { + http_client: reqwest::Client, + cfg: Config, +} + +impl Client { + /// Create a new client with given config + pub fn new(cfg: Config) -> Result { + let http_client = reqwest::Client::builder() + .no_gzip() + .http1_only() + .timeout(Duration::from_millis(cfg.http_req_timeout_millis.get())) + .tcp_keepalive(Duration::from_secs(7200)) + .connect_timeout(Duration::from_millis(cfg.http_req_timeout_millis.get())) + .build() + .unwrap(); + + Ok(Self { http_client, cfg }) + } + + /// Create a parquet file by executing a query. + /// + /// Path should point to a folder that will contain the parquet files in the end. + pub async fn create_parquet_folder(&self, query: Query, config: ParquetConfig) -> Result<()> { + parquet_out::create_parquet_folder(self, query, config).await + } + + /// Get the height of the source hypersync instance + pub async fn get_height(&self) -> Result { + let mut url = self.cfg.url.clone(); + let mut segments = url.path_segments_mut().ok().context("get path segments")?; + segments.push("height"); + std::mem::drop(segments); + let mut req = self.http_client.request(Method::GET, url); + + if let Some(bearer_token) = &self.cfg.bearer_token { + req = req.bearer_auth(bearer_token); + } + + let res = req.send().await.context("execute http req")?; + + let status = res.status(); + if !status.is_success() { + return Err(anyhow!("http response status code {}", status)); + } + + let height: ArchiveHeight = res.json().await.context("read response body json")?; + + Ok(height.height.unwrap_or(0)) + } + + /// Get the height of the source hypersync instance + /// Internally calls get_height. + /// On an error from the source hypersync instance, sleeps for + /// 1 second (increasing by 1 each failure up to max of 5 seconds) + /// and retries query until success. + pub async fn get_height_with_retry(&self) -> Result { + let mut base = 1; + + loop { + match self.get_height().await { + Ok(res) => return Ok(res), + Err(e) => { + log::error!("failed to send request to skar server: {:?}", e); + } + } + + let secs = Duration::from_secs(base); + let millis = Duration::from_millis(fastrange_rs::fastrange_64(rand::random(), 1000)); + + tokio::time::sleep(secs + millis).await; + + base = std::cmp::min(base + 1, 5); + } + } + + pub async fn stream( + &self, + query: Query, + config: StreamConfig, + ) -> Result>> { + let (tx, rx) = mpsc::channel(config.concurrency); + + let to_block = match query.to_block { + Some(to_block) => to_block, + None => { + if config.retry { + self.get_height_with_retry().await.context("get height")? + } else { + self.get_height().await.context("get height")? + } + } + }; + + let client = self.clone(); + let step = usize::try_from(config.batch_size).unwrap(); + tokio::spawn(async move { + let futs = (query.from_block..to_block) + .step_by(step) + .map(move |start| { + let end = cmp::min(start + config.batch_size, to_block); + let mut query = query.clone(); + query.from_block = start; + query.to_block = Some(end); + + Self::run_query_to_end(client.clone(), query, config.retry) + }); + + let mut stream = futures::stream::iter(futs).buffered(config.concurrency); + + while let Some(resps) = stream.next().await { + let resps = match resps { + Ok(resps) => resps, + Err(e) => { + tx.send(Err(e)).await.ok(); + return; + } + }; + + for resp in resps { + if tx.send(Ok(resp)).await.is_err() { + return; + } + } + } + }); + + Ok(rx) + } + + async fn run_query_to_end(self, query: Query, retry: bool) -> Result> { + let mut resps = Vec::new(); + + let to_block = query.to_block.unwrap(); + + let mut query = query; + + loop { + let resp = if retry { + self.send_with_retry::(&query) + .await + .context("send query")? + } else { + self.send::(&query) + .await + .context("send query")? + }; + + let next_block = resp.next_block; + + resps.push(resp); + + if next_block >= to_block { + break; + } else { + query.from_block = next_block; + } + } + + Ok(resps) + } + + /// Send a query request to the source hypersync instance. + /// + /// Returns a query response which contains block, tx and log data. + /// Format can be ArrowIpc or Parquet. + pub async fn send(&self, query: &Query) -> Result { + let mut url = self.cfg.url.clone(); + let mut segments = url.path_segments_mut().ok().context("get path segments")?; + segments.push("query"); + segments.push(Format::path()); + std::mem::drop(segments); + let mut req = self.http_client.request(Method::POST, url); + + if let Some(bearer_token) = &self.cfg.bearer_token { + req = req.bearer_auth(bearer_token); + } + + let res = req.json(&query).send().await.context("execute http req")?; + + let status = res.status(); + if !status.is_success() { + let text = res.text().await.context("read text to see error")?; + + return Err(anyhow!( + "http response status code {}, err body: {}", + status, + text + )); + } + + let bytes = res.bytes().await.context("read response body bytes")?; + + let res = tokio::task::block_in_place(|| { + Self::parse_query_response::(&bytes).context("parse query response") + })?; + + Ok(res) + } + + /// Send a query request to the source hypersync instance. + /// Internally calls send. + /// On an error from the source hypersync instance, sleeps for + /// 1 second (increasing by 1 each failure up to max of 5 seconds) + /// and retries query until success. + /// + /// Returns a query response which contains block, tx and log data. + /// Format can be ArrowIpc or Parquet. + pub async fn send_with_retry( + &self, + query: &Query, + ) -> Result { + let mut base = 1; + + loop { + match self.send::(query).await { + Ok(res) => return Ok(res), + Err(e) => { + log::error!("failed to send request to skar server: {:?}", e); + } + } + + let secs = Duration::from_secs(base); + let millis = Duration::from_millis(fastrange_rs::fastrange_64(rand::random(), 1000)); + + tokio::time::sleep(secs + millis).await; + + base = std::cmp::min(base + 1, 5); + } + } + + fn parse_query_response(bytes: &[u8]) -> Result { + let mut opts = capnp::message::ReaderOptions::new(); + opts.nesting_limit(i32::MAX).traversal_limit_in_words(None); + let message_reader = + capnp::serialize_packed::read_message(bytes, opts).context("create message reader")?; + + let query_response = message_reader + .get_root::() + .context("get root")?; + + let archive_height = match query_response.get_archive_height() { + -1 => None, + h => Some( + h.try_into() + .context("invalid archive height returned from server")?, + ), + }; + + let rollback_guard = if query_response.has_rollback_guard() { + let rg = query_response + .get_rollback_guard() + .context("get rollback guard")?; + + Some(RollbackGuard { + block_number: rg.get_block_number(), + timestamp: rg.get_timestamp(), + hash: rg + .get_hash() + .context("get rollback guard hash")? + .try_into() + .context("hash size")?, + first_block_number: rg.get_first_block_number(), + first_parent_hash: rg + .get_first_parent_hash() + .context("get rollback guard first parent hash")? + .try_into() + .context("hash size")?, + }) + } else { + None + }; + + let data = query_response.get_data().context("read data")?; + + let blocks = Format::read_chunks(data.get_blocks().context("get data")?) + .context("parse block data")?; + let transactions = Format::read_chunks(data.get_transactions().context("get data")?) + .context("parse tx data")?; + let logs = + Format::read_chunks(data.get_logs().context("get data")?).context("parse log data")?; + let traces = if data.has_traces() { + Format::read_chunks(data.get_traces().context("get data")?) + .context("parse traces data")? + } else { + Vec::new() + }; + + Ok(QueryResponse { + archive_height, + next_block: query_response.get_next_block(), + total_execution_time: query_response.get_total_execution_time(), + data: QueryResponseData { + blocks, + transactions, + logs, + traces, + }, + rollback_guard, + }) + } + + /// Returns a query for all Blocks and Transactions within the block range (from_block, to_block] + /// If to_block is None then query runs to the head of the chain. + pub fn preset_query_blocks_and_transactions(from_block: u64, to_block: Option) -> Query { + let all_block_fields: BTreeSet = skar_schema::block_header() + .fields + .iter() + .map(|x| x.name.clone()) + .collect(); + + let all_tx_fields: BTreeSet = skar_schema::transaction() + .fields + .iter() + .map(|x| x.name.clone()) + .collect(); + + Query { + from_block, + to_block, + transactions: vec![TransactionSelection::default()], + field_selection: FieldSelection { + block: all_block_fields, + transaction: all_tx_fields, + ..Default::default() + }, + ..Default::default() + } + } + + /// Returns a query object for all Blocks and hashes of the Transactions within the block range + /// (from_block, to_block]. Also returns the block_hash and block_number fields on each Transaction + /// so it can be mapped to a block. If to_block is None then query runs to the head of the chain. + pub fn preset_query_blocks_and_transaction_hashes( + from_block: u64, + to_block: Option, + ) -> Query { + let mut tx_field_selection = BTreeSet::new(); + tx_field_selection.insert("block_hash".to_owned()); + tx_field_selection.insert("block_number".to_owned()); + tx_field_selection.insert("hash".to_owned()); + + let all_block_fields: BTreeSet = skar_schema::block_header() + .fields + .iter() + .map(|x| x.name.clone()) + .collect(); + + Query { + from_block, + to_block, + transactions: vec![TransactionSelection::default()], + field_selection: FieldSelection { + block: all_block_fields, + transaction: tx_field_selection, + ..Default::default() + }, + ..Default::default() + } + } + + /// Returns a query object for all Logs within the block range from the given address. + /// If to_block is None then query runs to the head of the chain. + pub fn preset_query_logs(from_block: u64, to_block: Option, address: A) -> Result + where + A: TryInto
, + >::Error: Error + Send + Sync + 'static, + { + let address = address.try_into().context("convert Address type")?; + + let all_log_fields: BTreeSet = skar_schema::log() + .fields + .iter() + .map(|x| x.name.clone()) + .collect(); + + Ok(Query { + from_block, + to_block, + logs: vec![LogSelection { + address: vec![address], + ..Default::default() + }], + field_selection: FieldSelection { + log: all_log_fields, + ..Default::default() + }, + ..Default::default() + }) + } + + /// Returns a query for all Logs within the block range from the given address with a + /// matching topic0 event signature. Topic0 is the keccak256 hash of the event signature. + /// If to_block is None then query runs to the head of the chain. + pub fn preset_query_logs_of_event( + from_block: u64, + to_block: Option, + topic0: T, + address: A, + ) -> Result + where + A: TryInto
, + >::Error: Error + Send + Sync + 'static, + T: TryInto, + >::Error: Error + Send + Sync + 'static, + { + let topic0 = topic0.try_into().context("convert Topic0 type")?; + let mut topics = ArrayVec::, 4>::new(); + topics.insert(0, vec![topic0]); + + let address = address.try_into().context("convert Address type")?; + + let all_log_fields: BTreeSet = skar_schema::log() + .fields + .iter() + .map(|x| x.name.clone()) + .collect(); + + Ok(Query { + from_block, + to_block, + logs: vec![LogSelection { + address: vec![address], + topics, + }], + field_selection: FieldSelection { + log: all_log_fields, + ..Default::default() + }, + ..Default::default() + }) + } +} diff --git a/patch/skar-client-0.16.3/src/parquet_out.rs b/patch/skar-client-0.16.3/src/parquet_out.rs new file mode 100644 index 0000000..5dddac1 --- /dev/null +++ b/patch/skar-client-0.16.3/src/parquet_out.rs @@ -0,0 +1,783 @@ +use std::{ + collections::{BTreeMap, BTreeSet, VecDeque}, + path::PathBuf, + sync::Arc, + time::Instant, +}; + +use alloy_dyn_abi::{DynSolType, DynSolValue, ResolveSolEvent}; +use anyhow::{anyhow, Context, Result}; +use arrow2::{ + array::{ + Array, BinaryArray, MutableArray, MutableBinaryArray, MutableBooleanArray, + MutableUtf8Array, Utf8Array, + }, + datatypes::{DataType, Field, Schema}, + io::parquet::{ + read::ParquetError, + write::{ + array_to_columns, to_parquet_schema, to_parquet_type, transverse, CompressedPage, + DynIter, DynStreamingIterator, Encoding, FallibleStreamingIterator, RowGroupIter, + WriteOptions, + }, + }, +}; +use parquet2::write::FileStreamer; +use rayon::prelude::*; +use skar_net_types::Query; +use skar_schema::{concat_chunks, empty_chunk, project_schema}; +use tokio::{sync::mpsc, task::JoinHandle}; +use tokio_util::compat::TokioAsyncReadCompatExt; + +use crate::{ + column_mapping, rayon_async, types::StreamConfig, ArrowBatch, ArrowChunk, Client, ParquetConfig, +}; + +pub async fn create_parquet_folder( + client: &Client, + query: Query, + config: ParquetConfig, +) -> Result<()> { + let path = PathBuf::from(config.path); + + tokio::fs::create_dir_all(&path) + .await + .context("create parquet dir")?; + + let mut blocks_path = path.clone(); + blocks_path.push("blocks.parquet"); + let (mut blocks_sender, blocks_join) = spawn_writer( + blocks_path, + &skar_schema::block_header(), + Some(&query.field_selection.block), + &config.column_mapping.block, + config.hex_output, + )?; + + let mut transactions_path = path.clone(); + transactions_path.push("transactions.parquet"); + let (mut transactions_sender, transactions_join) = spawn_writer( + transactions_path, + &skar_schema::transaction(), + Some(&query.field_selection.transaction), + &config.column_mapping.transaction, + config.hex_output, + )?; + + let mut logs_path = path.clone(); + logs_path.push("logs.parquet"); + let (mut logs_sender, logs_join) = spawn_writer( + logs_path, + &skar_schema::log(), + Some(&query.field_selection.log), + &config.column_mapping.log, + config.hex_output, + )?; + + let mut traces_path = path.clone(); + traces_path.push("traces.parquet"); + let (mut traces_sender, traces_join) = spawn_writer( + traces_path, + &skar_schema::trace(), + Some(&query.field_selection.trace), + &config.column_mapping.trace, + config.hex_output, + )?; + + let event_signature = match &config.event_signature { + Some(sig) => Some(alloy_json_abi::Event::parse(sig).context("parse event signature")?), + None => None, + }; + + let mut decoded_logs_path = path.clone(); + decoded_logs_path.push("decoded_logs.parquet"); + let (mut decoded_logs_sender, decoded_logs_join) = spawn_writer( + decoded_logs_path, + &schema_from_event_signature(&event_signature) + .context("arrow schema from event signature")?, + None, + &config.column_mapping.decoded_log, + config.hex_output, + )?; + + let mut rx = client + .stream::( + query, + StreamConfig { + concurrency: config.concurrency, + batch_size: config.batch_size, + retry: config.retry, + }, + ) + .await + .context("start stream")?; + + while let Some(resp) = rx.recv().await { + let resp = resp.context("get query response")?; + + log::trace!("got data up to block {}", resp.next_block); + + let blocks_fut = async move { + for batch in resp.data.blocks { + blocks_sender + .send(batch) + .await + .context("write blocks chunk to parquet")?; + } + + Ok::<_, anyhow::Error>(blocks_sender) + }; + + let txs_fut = async move { + for batch in resp.data.transactions { + transactions_sender + .send(batch) + .await + .context("write transactions chunk to parquet")?; + } + + Ok::<_, anyhow::Error>(transactions_sender) + }; + + let logs_fut = { + let data = resp.data.logs.clone(); + async move { + for batch in data { + logs_sender + .send(batch) + .await + .context("write logs chunk to parquet")?; + } + + Ok::<_, anyhow::Error>(logs_sender) + } + }; + + let traces_fut = async move { + for batch in resp.data.traces { + traces_sender + .send(batch) + .await + .context("write traces chunk to parquet")?; + } + + Ok::<_, anyhow::Error>(traces_sender) + }; + + let sig = Arc::new(event_signature.clone()); + let decoded_logs_fut = async move { + for batch in resp.data.logs { + let sig = sig.clone(); + let batch = rayon_async::spawn(move || decode_logs_batch(&sig, batch)) + .await + .context("join decode logs task")? + .context("decode logs")?; + + decoded_logs_sender + .send(batch) + .await + .context("write decoded_logs chunk to parquet")?; + } + + Ok::<_, anyhow::Error>(decoded_logs_sender) + }; + + let start = Instant::now(); + + ( + blocks_sender, + transactions_sender, + logs_sender, + traces_sender, + decoded_logs_sender, + ) = futures::future::try_join5(blocks_fut, txs_fut, logs_fut, traces_fut, decoded_logs_fut) + .await + .context("write to parquet")?; + + log::trace!("wrote to parquet in {} ms", start.elapsed().as_millis()); + } + + std::mem::drop(blocks_sender); + std::mem::drop(transactions_sender); + std::mem::drop(logs_sender); + std::mem::drop(traces_sender); + std::mem::drop(decoded_logs_sender); + + blocks_join + .await + .context("join blocks task")? + .context("finish blocks file")?; + transactions_join + .await + .context("join transactions task")? + .context("finish transactions file")?; + logs_join + .await + .context("join logs task")? + .context("finish logs file")?; + traces_join + .await + .context("join traces task")? + .context("finish traces file")?; + decoded_logs_join + .await + .context("join decoded_logs task")? + .context("finish decoded_logs file")?; + + Ok(()) +} + +fn hex_encode_chunk(chunk: &ArrowChunk) -> anyhow::Result { + let cols = chunk + .columns() + .par_iter() + .map(|col| { + let col = match col.data_type() { + DataType::Binary => Box::new(hex_encode(col.as_any().downcast_ref().unwrap())), + _ => col.clone(), + }; + + Ok::<_, anyhow::Error>(col) + }) + .collect::>>()?; + + Ok(ArrowChunk::new(cols)) +} + +fn hex_encode(input: &BinaryArray) -> Utf8Array { + let mut arr = MutableUtf8Array::new(); + + for buf in input.iter() { + arr.push(buf.map(faster_hex::hex_string)); + } + + arr.into() +} + +fn spawn_writer( + path: PathBuf, + schema: &Schema, + field_selection: Option<&BTreeSet>, + mapping: &BTreeMap, + hex_output: bool, +) -> Result<(mpsc::Sender, JoinHandle>)> { + let schema = if let Some(field_selection) = field_selection { + project_schema(schema, field_selection).context("project schema")? + } else { + schema.clone() + }; + let schema = column_mapping::apply_to_schema(&schema, mapping) + .context("apply column mapping to schema")?; + let schema = if hex_output { + Schema::from( + schema + .fields + .iter() + .map(|field| match field.data_type() { + DataType::Binary => { + Field::new(field.name.clone(), DataType::Utf8, field.is_nullable) + } + _ => field.clone(), + }) + .collect::>(), + ) + } else { + schema + }; + + let (tx, rx) = mpsc::channel(64); + + let mapping = Arc::new(mapping.clone()); + + let handle = tokio::task::spawn(async move { + match run_writer(rx, path, schema, mapping, hex_output).await { + Ok(v) => Ok(v), + Err(e) => { + log::error!("failed to run parquet writer: {:?}", e); + Err(e) + } + } + }); + + Ok((tx, handle)) +} + +async fn run_writer( + mut rx: mpsc::Receiver, + path: PathBuf, + schema: Schema, + mapping: Arc>, + hex_output: bool, +) -> Result<()> { + let write_options = parquet2::write::WriteOptions { + write_statistics: true, + version: parquet2::write::Version::V2, + }; + + let file = tokio::fs::File::create(&path) + .await + .context("create parquet file")? + .compat(); + + let parquet_schema = to_parquet_schema(&schema).context("to parquet schema")?; + + let schema = Arc::new(schema); + + let mut writer = FileStreamer::new(file, parquet_schema, write_options, None); + + let num_cpus = num_cpus::get(); + let mut encode_jobs = VecDeque::::with_capacity(num_cpus); + + let mut data = Vec::new(); + let mut total_rows = 0; + loop { + let mut stop = false; + if let Some(batch) = rx.recv().await { + total_rows += batch.chunk.len(); + data.push(batch); + } else { + stop = true; + } + + if !data.is_empty() && (stop || total_rows >= ROW_GROUP_MAX_ROWS) { + if encode_jobs.len() >= num_cpus { + let fut = encode_jobs.pop_front().unwrap(); + let rg = fut + .await + .context("join prepare task")? + .context("prepare row group")?; + writer + .write(rg) + .await + .context("write encoded row group to file")?; + } + + let batches = std::mem::take(&mut data); + total_rows = 0; + let chunks = batches + .into_iter() + .map(|b| Arc::new(b.chunk)) + .collect::>(); + + let chunk = concat_chunks(chunks.as_slice()).context("concat chunks")?; + + let mapping = mapping.clone(); + let schema = schema.clone(); + let fut = rayon_async::spawn(move || { + let field_names = schema + .fields + .iter() + .map(|f| f.name.as_str()) + .collect::>(); + let chunk = column_mapping::apply_to_chunk(&chunk, &field_names, &mapping) + .context("apply column mapping to batch")?; + + let chunk = if hex_output { + hex_encode_chunk(&chunk).context("hex encode batch")? + } else { + chunk + }; + + encode_row_group( + ArrowBatch { chunk, schema }, + WriteOptions { + write_statistics: true, + version: arrow2::io::parquet::write::Version::V2, + compression: arrow2::io::parquet::write::CompressionOptions::Lz4Raw, + data_pagesize_limit: None, + }, + ) + }); + + encode_jobs.push_back(fut); + } + + if stop { + break; + } + } + + while let Some(fut) = encode_jobs.pop_front() { + let rg = fut + .await + .context("join prepare task")? + .context("prepare row group")?; + writer + .write(rg) + .await + .context("write encoded row group to file")?; + } + + let _size = writer.end(None).await.context("write footer")?; + + Ok(()) +} + +type EncodeFut = tokio::sync::oneshot::Receiver< + Result< + DynIter< + 'static, + std::result::Result< + DynStreamingIterator<'static, CompressedPage, arrow2::error::Error>, + arrow2::error::Error, + >, + >, + >, +>; + +fn encode_row_group( + batch: ArrowBatch, + write_options: WriteOptions, +) -> Result> { + let fields = batch + .schema + .fields + .iter() + .map(|field| to_parquet_type(field).context("map to parquet field")) + .collect::>>()?; + let encodings = batch + .schema + .fields + .iter() + .map(|f| transverse(&f.data_type, |_| Encoding::Plain)) + .collect::>(); + + let data = batch + .chunk + .into_arrays() + .into_iter() + .zip(fields) + .zip(encodings) + .flat_map(move |((array, type_), encoding)| { + let encoded_columns = array_to_columns(array, type_, write_options, &encoding).unwrap(); + encoded_columns + .into_iter() + .map(|encoded_pages| { + let pages = encoded_pages; + + let pages = DynIter::new( + pages + .into_iter() + .map(|x| x.map_err(|e| ParquetError::OutOfSpec(e.to_string()))), + ); + + let compressed_pages = pages + .map(|page| { + let page = page?; + arrow2::io::parquet::write::compress( + page, + vec![], + write_options.compression, + ) + .map_err(arrow2::error::Error::from) + }) + .collect::>(); + + Ok(DynStreamingIterator::new(CompressedPageIter { + data: compressed_pages.into_iter(), + current: None, + })) + }) + .collect::>() + }) + .collect::>(); + Ok(DynIter::new(data.into_iter())) +} + +struct CompressedPageIter { + data: std::vec::IntoIter>, + current: Option, +} + +impl FallibleStreamingIterator for CompressedPageIter { + type Item = CompressedPage; + type Error = arrow2::error::Error; + + fn get(&self) -> Option<&Self::Item> { + self.current.as_ref() + } + + fn advance(&mut self) -> std::result::Result<(), Self::Error> { + self.current = match self.data.next() { + Some(page) => Some(page?), + None => None, + }; + Ok(()) + } +} + +const ROW_GROUP_MAX_ROWS: usize = 10_000; + +fn decode_logs_batch(sig: &Option, batch: ArrowBatch) -> Result { + let schema = + schema_from_event_signature(sig).context("build arrow schema from event signature")?; + + if batch.chunk.is_empty() { + return Ok(ArrowBatch { + chunk: empty_chunk(&schema), + schema: Arc::new(schema), + }); + } + + let sig = match sig { + Some(sig) => sig, + None => { + return Ok(ArrowBatch { + chunk: empty_chunk(&schema), + schema: Arc::new(schema), + }) + } + }; + + let event = sig.resolve().context("resolve signature into event")?; + + let topic_cols = event + .indexed() + .iter() + .zip(["topic1", "topic2", "topic3"].iter()) + .map(|(decoder, topic_name)| { + let col = batch + .column::>(topic_name) + .context("get column")?; + let col = decode_col(col, decoder).context("decode column")?; + Ok::<_, anyhow::Error>(col) + }) + .collect::>>()?; + + let body_cols = if event.body() == [DynSolType::Uint(256)] { + let data = batch + .column::>("data") + .context("get column")?; + vec![decode_erc20_amount(data, &DynSolType::Uint(256)).context("decode amount column")?] + } else if !event.body().is_empty() { + let data = batch + .column::>("data") + .context("get column")?; + + let tuple_decoder = DynSolType::Tuple(event.body().to_vec()); + + let mut decoded_tuples = Vec::with_capacity(data.len()); + for val in data.values_iter() { + let tuple = tuple_decoder + .abi_decode(val) + .context("decode body tuple")? + .as_tuple() + .context("expected tuple after decoding")? + .to_vec(); + + if tuple.len() != event.body().len() { + return Err(anyhow!( + "expected tuple of length {} after decoding", + event.body().len() + )); + } + + decoded_tuples.push(tuple); + } + + let mut decoded_cols = Vec::with_capacity(event.body().len()); + + for (i, ty) in event.body().iter().enumerate() { + decoded_cols.push( + decode_body_col(decoded_tuples.iter().map(|t| t.get(i).unwrap()), ty) + .context("decode body column")?, + ); + } + + decoded_cols + } else { + Vec::new() + }; + + let mut cols = topic_cols; + cols.extend_from_slice(&body_cols); + + let chunk = ArrowChunk::try_new(cols).context("create arrow chunk")?; + + Ok(ArrowBatch { + chunk, + schema: Arc::new(schema), + }) +} + +fn decode_body_col<'a, I: ExactSizeIterator>( + vals: I, + ty: &DynSolType, +) -> Result> { + match ty { + DynSolType::Bool => { + let mut builder = MutableBooleanArray::with_capacity(vals.len()); + + for val in vals { + match val { + DynSolValue::Bool(b) => builder.push(Some(*b)), + v => { + return Err(anyhow!( + "unexpected output type from decode: {:?}", + v.as_type() + )) + } + } + } + + Ok(builder.as_box()) + } + _ => { + let mut builder = MutableBinaryArray::::new(); + + for val in vals { + match val { + DynSolValue::Int(v, _) => builder.push(Some(v.to_be_bytes::<32>())), + DynSolValue::Uint(v, _) => builder.push(Some(v.to_be_bytes::<32>())), + DynSolValue::FixedBytes(v, _) => builder.push(Some(v)), + DynSolValue::Address(v) => builder.push(Some(v)), + DynSolValue::Bytes(v) => builder.push(Some(v)), + DynSolValue::String(v) => builder.push(Some(v)), + v => { + return Err(anyhow!( + "unexpected output type from decode: {:?}", + v.as_type() + )) + } + } + } + + Ok(builder.as_box()) + } + } +} + +fn decode_erc20_amount(data: &BinaryArray, decoder: &DynSolType) -> Result> { + let mut builder = MutableBinaryArray::::new(); + + for val in data.values_iter() { + // Check if we are decoding a single u256 and the body is empty + // + // This case can happen when decoding zero value erc20 transfers + let v = if val.is_empty() { + [0; 32].as_slice() + } else { + val + }; + + match decoder.abi_decode(v).context("decode val")? { + DynSolValue::Uint(v, _) => builder.push(Some(v.to_be_bytes::<32>())), + v => { + return Err(anyhow!( + "unexpected output type from decode: {:?}", + v.as_type() + )) + } + } + } + + Ok(builder.as_box()) +} + +fn decode_col(col: &BinaryArray, decoder: &DynSolType) -> Result> { + match decoder { + DynSolType::Bool => { + let mut builder = MutableBooleanArray::with_capacity(col.len()); + + for val in col.iter() { + let val = val.context("found null value")?; + match decoder.abi_decode(val).context("decode sol value")? { + DynSolValue::Bool(b) => builder.push(Some(b)), + v => { + return Err(anyhow!( + "unexpected output type from decode: {:?}", + v.as_type() + )) + } + } + } + + Ok(builder.as_box()) + } + _ => { + let mut builder = MutableBinaryArray::::new(); + + for val in col.iter() { + let val = val.context("found null value")?; + + match decoder.abi_decode(val).context("decode sol value")? { + DynSolValue::Int(v, _) => builder.push(Some(v.to_be_bytes::<32>())), + DynSolValue::Uint(v, _) => builder.push(Some(v.to_be_bytes::<32>())), + DynSolValue::FixedBytes(v, _) => builder.push(Some(v)), + DynSolValue::Address(v) => builder.push(Some(v)), + DynSolValue::Bytes(v) => builder.push(Some(v)), + DynSolValue::String(v) => builder.push(Some(v)), + v => { + return Err(anyhow!( + "unexpected output type from decode: {:?}", + v.as_type() + )) + } + } + } + + Ok(builder.as_box()) + } + } +} + +fn schema_from_event_signature(sig: &Option) -> Result { + let sig = match sig { + Some(sig) => sig, + None => { + return Ok(Schema::from(vec![Field::new( + "dummy", + DataType::Boolean, + true, + )])); + } + }; + + let event = sig.resolve().context("resolve signature into event")?; + + let mut fields: Vec = Vec::with_capacity(sig.inputs.len()); + + for (input, resolved_type) in sig + .inputs + .iter() + .zip(event.indexed().iter().chain(event.body().iter())) + { + if input.name.is_empty() { + return Err(anyhow!("empty param names are not supported")); + } + + if fields + .iter() + .any(|f| f.name.as_str() == input.name.as_str()) + { + return Err(anyhow!("duplicate param name: {}", input.name)); + } + + let ty = DynSolType::parse(&input.ty).context("parse solidity type")?; + + if &ty != resolved_type { + return Err(anyhow!("Internal error: Parsed type doesn't match resolved type. This should never happen.")); + } + + let dt = simple_type_to_data_type(&ty).context("convert simple type to arrow datatype")?; + fields.push(Field::new(input.name.clone(), dt, false)); + } + + Ok(Schema::from(fields)) +} + +fn simple_type_to_data_type(ty: &DynSolType) -> Result { + match ty { + DynSolType::Bool => Ok(DataType::Boolean), + DynSolType::Int(_) => Ok(DataType::Binary), + DynSolType::Uint(_) => Ok(DataType::Binary), + DynSolType::FixedBytes(_) => Ok(DataType::Binary), + DynSolType::Address => Ok(DataType::Binary), + DynSolType::Bytes => Ok(DataType::Binary), + DynSolType::String => Ok(DataType::Binary), + ty => Err(anyhow!( + "Complex types are not supported. Unexpected type: {}", + ty + )), + } +} diff --git a/patch/skar-client-0.16.3/src/rayon_async.rs b/patch/skar-client-0.16.3/src/rayon_async.rs new file mode 100644 index 0000000..cecd585 --- /dev/null +++ b/patch/skar-client-0.16.3/src/rayon_async.rs @@ -0,0 +1,16 @@ +use tokio::sync::oneshot; + +pub fn spawn(func: F) -> oneshot::Receiver +where + F: 'static + FnOnce() -> T + Send, + T: 'static + Send + Sync, +{ + let (tx, rx) = oneshot::channel(); + + rayon::spawn(move || { + let res = func(); + tx.send(res).ok(); + }); + + rx +} diff --git a/patch/skar-client-0.16.3/src/transport_format.rs b/patch/skar-client-0.16.3/src/transport_format.rs new file mode 100644 index 0000000..efd165f --- /dev/null +++ b/patch/skar-client-0.16.3/src/transport_format.rs @@ -0,0 +1,39 @@ +use std::{io::Cursor, sync::Arc}; + +use crate::ArrowBatch; +use anyhow::{Context, Result}; +use arrow2::io::ipc; + +pub trait TransportFormat { + fn read_chunks(bytes: &[u8]) -> Result>; + fn path() -> &'static str; +} + +pub struct ArrowIpc; + +impl TransportFormat for ArrowIpc { + fn read_chunks(bytes: &[u8]) -> Result> { + let mut reader = Cursor::new(bytes); + + let metadata = ipc::read::read_file_metadata(&mut reader).context("read metadata")?; + + let schema = Arc::new(metadata.schema.clone()); + + let reader = ipc::read::FileReader::new(reader, metadata, None, None); + + let chunks = reader + .map(|chunk| { + chunk.context("read chunk").map(|chunk| ArrowBatch { + chunk, + schema: schema.clone(), + }) + }) + .collect::>>()?; + + Ok(chunks) + } + + fn path() -> &'static str { + "arrow-ipc" + } +} diff --git a/patch/skar-client-0.16.3/src/types.rs b/patch/skar-client-0.16.3/src/types.rs new file mode 100644 index 0000000..ceaaa6e --- /dev/null +++ b/patch/skar-client-0.16.3/src/types.rs @@ -0,0 +1,104 @@ +use crate::{column_mapping::ColumnMapping, ArrowChunk}; +use anyhow::{anyhow, Context, Result}; +use arrow2::datatypes::SchemaRef; +use serde::{Deserialize, Serialize}; +use skar_net_types::RollbackGuard; + +#[derive(Debug, Clone)] +pub struct QueryResponseData { + pub blocks: Vec, + pub transactions: Vec, + pub logs: Vec, + pub traces: Vec, +} + +#[derive(Debug, Clone)] +pub struct QueryResponse { + /// Current height of the source hypersync instance + pub archive_height: Option, + /// Next block to query for, the responses are paginated so + /// the caller should continue the query from this block if they + /// didn't get responses up to the to_block they specified in the Query. + pub next_block: u64, + /// Total time it took the hypersync instance to execute the query. + pub total_execution_time: u64, + /// Response data + pub data: QueryResponseData, + /// Rollback guard + pub rollback_guard: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct StreamConfig { + #[serde(default = "default_batch_size")] + /// Block range size to use when making individual requests. + pub batch_size: u64, + #[serde(default = "default_concurrency")] + /// Controls the number of concurrent requests made to hypersync server. + pub concurrency: usize, + /// Requests are retried forever internally if this param is set to true. + #[serde(default)] + pub retry: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ParquetConfig { + /// Path to write parquet files to + pub path: String, + /// Define type mapping for output columns + #[serde(default)] + pub column_mapping: ColumnMapping, + /// Event signature to parse the logs with. example: Transfer(address indexed from, address indexed to, uint256 amount) + pub event_signature: Option, + /// Convert binary output columns to hex + #[serde(default)] + pub hex_output: bool, + #[serde(default = "default_batch_size")] + /// Block range size to use when making individual requests. + pub batch_size: u64, + #[serde(default = "default_concurrency")] + /// Controls the number of concurrent requests made to hypersync server. + pub concurrency: usize, + /// Requests are retried forever internally if this param is set to true. + #[serde(default)] + pub retry: bool, +} + +fn default_batch_size() -> u64 { + 400 +} + +fn default_concurrency() -> usize { + 10 +} + +#[derive(Debug, Clone)] +pub struct ArrowBatch { + pub chunk: ArrowChunk, + pub schema: SchemaRef, +} + +impl ArrowBatch { + pub fn column(&self, name: &str) -> Result<&T> { + match self + .schema + .fields + .iter() + .enumerate() + .find(|(_, f)| f.name == name) + { + Some((idx, _)) => { + let col = self + .chunk + .columns() + .get(idx) + .context("get column")? + .as_any() + .downcast_ref::() + .context("cast column type")?; + Ok(col) + } + None => Err(anyhow!("field {} not found in schema", name)), + } + } +} diff --git a/patch/skar-client-0.16.3/test-data/ens_token_abi.json b/patch/skar-client-0.16.3/test-data/ens_token_abi.json new file mode 100644 index 0000000..1eef4e3 --- /dev/null +++ b/patch/skar-client-0.16.3/test-data/ens_token_abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"uint256","name":"freeSupply","type":"uint256"},{"internalType":"uint256","name":"airdropSupply","type":"uint256"},{"internalType":"uint256","name":"_claimPeriodEnds","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"MerkleRootChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"pos","type":"uint32"}],"name":"checkpoints","outputs":[{"components":[{"internalType":"uint32","name":"fromBlock","type":"uint32"},{"internalType":"uint224","name":"votes","type":"uint224"}],"internalType":"struct ERC20Votes.Checkpoint","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimPeriodEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumMintInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dest","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dest","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}] diff --git a/patch/skar-client-0.16.3/test-data/erc20.abi.json b/patch/skar-client-0.16.3/test-data/erc20.abi.json new file mode 100644 index 0000000..06b572d --- /dev/null +++ b/patch/skar-client-0.16.3/test-data/erc20.abi.json @@ -0,0 +1,222 @@ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + } +] diff --git a/patch/skar-client-0.16.3/test-data/nameless.abi.json b/patch/skar-client-0.16.3/test-data/nameless.abi.json new file mode 100644 index 0000000..2d9ce2f --- /dev/null +++ b/patch/skar-client-0.16.3/test-data/nameless.abi.json @@ -0,0 +1 @@ +[{"type":"event","name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"approved","type":"address","indexed":true},{"name":"tokenId","type":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ApprovalForAll","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"operator","type":"address","indexed":true},{"name":"approved","type":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"CancelLockupStream","inputs":[{"name":"streamId","type":"uint256","indexed":false},{"name":"sender","type":"address","indexed":true},{"name":"recipient","type":"address","indexed":true},{"name":"asset","type":"address","indexed":true},{"name":"senderAmount","type":"uint128","indexed":false},{"name":"recipientAmount","type":"uint128","indexed":false}],"anonymous":false},{"type":"event","name":"CreateLockupDynamicStream","inputs":[{"name":"streamId","type":"uint256","indexed":false},{"name":"funder","type":"address","indexed":false},{"name":"sender","type":"address","indexed":true},{"name":"recipient","type":"address","indexed":true},{"name":"amounts","type":"tuple","indexed":false,"components":[{"type":"uint128"},{"type":"uint128"},{"type":"uint128"}]},{"name":"asset","type":"address","indexed":true},{"name":"cancelable","type":"bool","indexed":false},{"name":"transferable","type":"bool","indexed":false},{"name":"segments","type":"tuple[]","indexed":false,"components":[{"type":"uint128"},{"type":"uint64"},{"type":"uint40"}]},{"name":"range","type":"tuple","indexed":false,"components":[{"type":"uint40"},{"type":"uint40"}]},{"name":"broker","type":"address","indexed":false}],"anonymous":false},{"type":"event","name":"CreateLockupLinearStream","inputs":[{"name":"streamId","type":"uint256","indexed":false},{"name":"funder","type":"address","indexed":false},{"name":"sender","type":"address","indexed":true},{"name":"recipient","type":"address","indexed":true},{"name":"amounts","type":"tuple","indexed":false,"components":[{"type":"uint128"},{"type":"uint128"},{"type":"uint128"}]},{"name":"asset","type":"address","indexed":true},{"name":"cancelable","type":"bool","indexed":false},{"name":"transferable","type":"bool","indexed":false},{"name":"range","type":"tuple","indexed":false,"components":[{"type":"uint40"},{"type":"uint40"},{"type":"uint40"}]},{"name":"broker","type":"address","indexed":false}],"anonymous":false},{"type":"event","name":"RenounceLockupStream","inputs":[{"name":"streamId","type":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"tokenId","type":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"TransferAdmin","inputs":[{"name":"oldAdmin","type":"address","indexed":true},{"name":"newAdmin","type":"address","indexed":true}],"anonymous":false},{"type":"event","name":"WithdrawFromLockupStream","inputs":[{"name":"streamId","type":"uint256","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"asset","type":"address","indexed":true},{"name":"amount","type":"uint128","indexed":false}],"anonymous":false}] \ No newline at end of file diff --git a/patch/skar-client-0.16.3/tests/api_test.rs b/patch/skar-client-0.16.3/tests/api_test.rs new file mode 100644 index 0000000..31b5114 --- /dev/null +++ b/patch/skar-client-0.16.3/tests/api_test.rs @@ -0,0 +1,394 @@ +use std::{collections::BTreeSet, env::temp_dir}; + +use alloy_dyn_abi::DynSolValue; +use alloy_json_abi::JsonAbi; +use arrow2::array::UInt64Array; +use skar_client::{ArrowIpc, Client, ColumnMapping, Config, Decoder, ParquetConfig}; +use skar_format::{Address, Hex, LogArgument}; +use skar_net_types::{FieldSelection, Query}; + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_arrow_ipc() { + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + + let mut block_field_selection = BTreeSet::new(); + block_field_selection.insert("number".to_owned()); + block_field_selection.insert("timestamp".to_owned()); + block_field_selection.insert("hash".to_owned()); + + let res = client + .send::(&Query { + from_block: 14000000, + to_block: None, + logs: Vec::new(), + transactions: Vec::new(), + include_all_blocks: true, + field_selection: FieldSelection { + block: block_field_selection, + log: Default::default(), + transaction: Default::default(), + trace: Default::default(), + }, + ..Default::default() + }) + .await + .unwrap(); + + dbg!(res.next_block); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_arrow_ipc_ordering() { + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + + let mut block_field_selection = BTreeSet::new(); + block_field_selection.insert("number".to_owned()); + + let query: Query = serde_json::from_value(serde_json::json!({ + "from_block": 13171881, + "to_block": 18270333, + "logs": [ + { + "address": [ + "0x15b7c0c907e4C6b9AdaAaabC300C08991D6CEA05" + ], + "topics": [ + [ + "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + ] + ] + } + ], + "field_selection": { + "block": [ + "number" + ], + "log": [ + "log_index", + "block_number" + ] + } + })) + .unwrap(); + + let res = client.send::(&query).await.unwrap(); + + assert!(res.next_block > 13223105); + + let mut last = (0, 0); + for batch in res.data.logs { + let block_number = batch.column::("block_number").unwrap(); + let log_index = batch.column::("log_index").unwrap(); + + for (&block_number, &log_index) in block_number.values_iter().zip(log_index.values_iter()) { + let number = (block_number, log_index); + assert!(last < number, "last: {:?};number: {:?};", last, number); + last = number; + } + } +} + +fn get_file_path(name: &str) -> String { + format!("{}/test-data/{name}", env!("CARGO_MANIFEST_DIR")) +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_decode_logs() { + const ADDR: &str = "0xc18360217d8f7ab5e7c516566761ea12ce7f9d72"; + let address = Address::decode_hex(ADDR).unwrap(); + + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + + let query: Query = serde_json::from_value(serde_json::json!({ + "from_block": 18680952, + "to_block": 18680953, + "logs": [ + { + "address": [ + ADDR + ] + } + ], + "field_selection": { + "log": [ + "address", + "data", + "topic0", + "topic1", + "topic2", + "topic3" + ] + } + })) + .unwrap(); + + let res = client.send::(&query).await.unwrap(); + + let path = get_file_path("ens_token_abi.json"); + let abi = tokio::fs::read_to_string(path).await.unwrap(); + let abi: JsonAbi = serde_json::from_str(&abi).unwrap(); + + let decoder = Decoder::new(&[(address, abi)]).unwrap(); + + let decoded_logs = decoder.decode_logs(&res.data.logs).unwrap().unwrap(); + + assert_eq!(decoded_logs.len(), 1); + + println!("{:?}", decoded_logs[0]); +} + +const URL: &str = "https://eth.hypersync.xyz"; + +#[test] +fn decode_zero_erc20_transfer() { + const ADDR: &str = "0xc18360217d8f7ab5e7c516566761ea12ce7f9d72"; + let address = Address::decode_hex(ADDR).unwrap(); + + let path = get_file_path("erc20.abi.json"); + let abi = std::fs::read_to_string(path).unwrap(); + let abi: JsonAbi = serde_json::from_str(&abi).unwrap(); + + let decoder = Decoder::new(&[(address.clone(), abi)]).unwrap(); + + let topics = [ + Some( + LogArgument::decode_hex( + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + ) + .unwrap(), + ), + Some( + LogArgument::decode_hex( + "0x000000000000000000000000327339b55b16345a4b206bfb09c3fa27ab4689ec", + ) + .unwrap(), + ), + Some( + LogArgument::decode_hex( + "0x0000000000000000000000001e037f97d730cc881e77f01e409d828b0bb14de0", + ) + .unwrap(), + ), + None, + ]; + + let topics = topics + .iter() + .map(|t| t.as_ref().map(|t| t.as_slice())) + .collect::>(); + + let event = decoder + .decode( + address.as_slice(), + topics[0].unwrap(), + topics.as_slice(), + &[], + ) + .unwrap() + .unwrap(); + + assert_eq!(event.body[0], DynSolValue::Uint(0.try_into().unwrap(), 256)); +} + +#[test] +fn parse_nameless_abi() { + let path = get_file_path("nameless.abi.json"); + let abi = std::fs::read_to_string(path).unwrap(); + let _abi: JsonAbi = serde_json::from_str(&abi).unwrap(); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_parquet_out() { + env_logger::try_init().ok(); + + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + + let path = format!("{}/{}", temp_dir().to_string_lossy(), uuid::Uuid::new_v4()); + + let query: Query = serde_json::from_value(serde_json::json!({ + "from_block": 19277345, + "to_block": 19277346, + "logs": [{ + "address": ["0xdAC17F958D2ee523a2206206994597C13D831ec7"], + "topics": [["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]], + }], + "transactions": [{}], + "include_all_blocks": true, + "field_selection": { + "log": ["block_number"], + } + })) + .unwrap(); + + client + .create_parquet_folder( + query, + ParquetConfig { + path, + hex_output: true, + batch_size: 100, + concurrency: 10, + retry: false, + column_mapping: ColumnMapping { + block: maplit::btreemap! { + "number".to_owned() => skar_client::DataType::Float32, + }, + transaction: maplit::btreemap! { + "value".to_owned() => skar_client::DataType::Float64, + }, + log: Default::default(), + trace: Default::default(), + decoded_log: maplit::btreemap! { + "value".to_owned() => skar_client::DataType::Float64, + }, + }, + event_signature: None, + }, + ) + .await + .unwrap(); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_preset_query_blocks_and_transactions() { + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + let query = Client::preset_query_blocks_and_transactions(18_000_000, Some(18_000_100)); + let res = client.send::(&query).await.unwrap(); + + let num_blocks: usize = res + .data + .blocks + .into_iter() + .map(|batch| batch.chunk.len()) + .sum(); + let num_txs: usize = res + .data + .transactions + .into_iter() + .map(|batch| batch.chunk.len()) + .sum(); + + assert!(res.next_block == 18_000_100); + assert!(num_blocks == 100); + assert!(num_txs > 1); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_preset_query_blocks_and_transaction_hashes() { + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + let query = Client::preset_query_blocks_and_transaction_hashes(18_000_000, Some(18_000_100)); + let res = client.send::(&query).await.unwrap(); + + let num_blocks: usize = res + .data + .blocks + .into_iter() + .map(|batch| batch.chunk.len()) + .sum(); + let num_txs: usize = res + .data + .transactions + .into_iter() + .map(|batch| batch.chunk.len()) + .sum(); + + assert!(res.next_block == 18_000_100); + assert!(num_blocks == 100); + assert!(num_txs > 1); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_preset_query_logs() { + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + + let usdt_addr = hex_literal::hex!("dAC17F958D2ee523a2206206994597C13D831ec7"); + let query = Client::preset_query_logs(18_000_000, Some(18_001_000), usdt_addr).unwrap(); + let res = client.send::(&query).await.unwrap(); + + let num_logs: usize = res + .data + .logs + .into_iter() + .map(|batch| batch.chunk.len()) + .sum(); + + assert!(res.next_block == 18_001_000); + assert!(num_logs > 1); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_api_preset_query_logs_of_event() { + let client = Client::new(Config { + url: URL.parse().unwrap(), + bearer_token: None, + http_req_timeout_millis: 20000.try_into().unwrap(), + }) + .unwrap(); + + let usdt_addr = hex_literal::hex!("dAC17F958D2ee523a2206206994597C13D831ec7"); + let transfer_topic0 = + hex_literal::hex!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"); + let query = Client::preset_query_logs_of_event( + 18_000_000, + Some(18_001_000), + transfer_topic0, + usdt_addr, + ) + .unwrap(); + + let res = client.send::(&query).await.unwrap(); + + let num_logs: usize = res + .data + .logs + .into_iter() + .map(|batch| batch.chunk.len()) + .sum(); + + assert!(res.next_block == 18_001_000); + assert!(num_logs > 1); +} diff --git a/src/decode.rs b/src/decode.rs index ab722f9..09d8d16 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -126,19 +126,7 @@ impl Decoder { .context("decode log")? { Some(decoded) => decoded, - None => { - let address = Address::decode_hex("0x0000000000000000000000000000000000000000") - .context("decode address")?; - - match self - .inner - .decode(address.as_slice(), topic0, &topics, &data) - .context("decode log")? - { - Some(decoded) => decoded, - None => return Ok(None), - } - } + None => return Ok(None), }; Ok(Some(DecodedEvent { diff --git a/src/lib.rs b/src/lib.rs index b2f9e38..d268b1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,7 +82,7 @@ impl HypersyncClient { .map(|log| { let mut log = log; let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; } log @@ -129,7 +129,7 @@ impl HypersyncClient { .map(|log| { let mut log = log; let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; } log @@ -172,7 +172,7 @@ impl HypersyncClient { .map(|log| { let mut log = log; let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; } log @@ -207,7 +207,7 @@ impl HypersyncClient { .map(|log| { let mut log = log; let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; } log @@ -265,7 +265,7 @@ impl HypersyncClient { .map(|log| { let mut log = log; let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref() == [0u8; 20]) { + if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; } log From 92ba4c76a12ac3e4d6391f78cb45c6fc9c135f64 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Mon, 13 May 2024 07:01:26 -0400 Subject: [PATCH 3/9] fix: Allow hypersync queries with sigHash. --- src/lib.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d268b1f..44ecdc6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -575,7 +575,9 @@ fn convert_response_to_events(res: skar_client::QueryResponse) -> Result let mut events = Vec::with_capacity(logs.len()); for log in logs.into_iter() { - let transaction = txs.get(&(log.block_number, log.transaction_index)).cloned(); + let transaction = txs + .remove(&(log.block_number, log.transaction_index)) + .clone(); let block = blocks.get(&log.block_number).cloned(); events.push(Event { @@ -585,6 +587,24 @@ fn convert_response_to_events(res: skar_client::QueryResponse) -> Result }) } + for ((block_number, transaction_index), transaction) in txs.into_iter() { + events.push(Event { + log: Log { + block_hash: transaction.block_hash.clone(), + block_number: transaction.block_number, + log_index: -1, + address: transaction.contract_address.clone(), + transaction_index, + transaction_hash: transaction.hash.clone(), + data: None, + topics: vec![], + removed: None, + }, + block: blocks.get(&block_number).cloned(), + transaction: Some(transaction), + }) + } + Ok(Events { archive_height: res.archive_height.map(|h| h.try_into().unwrap()), next_block: res.next_block.try_into().unwrap(), From 570ae076fc3c7aa5649ad07c920b9c028a859be5 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Tue, 14 May 2024 08:31:37 -0400 Subject: [PATCH 4/9] fix: Remove debug messaging --- src/lib.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 44ecdc6..33c396f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,8 @@ mod types; use config::{Config, ParquetConfig, StreamConfig}; use query::Query; -use skar_format::Hex; +use skar_format::{FixedSizeData, Hex}; +use skar_net_types::TransactionSelection; use tokio::sync::mpsc; use types::{Block, Event, Log, Transaction}; @@ -258,6 +259,8 @@ impl HypersyncClient { } } + let mut transactions = Vec::::new(); + // 0x0000... is a special address that means no address query.logs = query .logs @@ -267,6 +270,25 @@ impl HypersyncClient { let address = log.address.clone(); if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; + } else { + let topics = log.topics.clone(); + let sighash: Option>> = topics.first().cloned(); + if let Some(sighash) = sighash { + let sighash = sighash + .iter() + .map(|v| { + let mut data = [0u8; 4]; + data.copy_from_slice(&v.as_slice()[0..4]); + FixedSizeData::from(data) + }) + .collect(); + transactions.push(TransactionSelection { + to: log.address.clone(), + from: vec![], + sighash, + status: None, + }); + }; } log }) @@ -525,6 +547,7 @@ pub struct QueryResponse { const BLOCK_JOIN_FIELDS: &[&str] = &["number"]; const TX_JOIN_FIELDS: &[&str] = &["block_number", "transaction_index"]; const LOG_JOIN_FIELDS: &[&str] = &["log_index", "transaction_index", "block_number"]; +const REFINE_TOPIC: &str = "0xea2555830810ebb32141e4d1bde9d6fe2497e7fbefadad253cc27c9721240fe3"; #[napi(object)] pub struct Events { @@ -588,16 +611,47 @@ fn convert_response_to_events(res: skar_client::QueryResponse) -> Result } for ((block_number, transaction_index), transaction) in txs.into_iter() { + let selector = transaction.input.clone(); + let selector: Option = if let Some(selector) = selector { + if selector.len() >= 4 { + Some(selector[0..10].to_string()) + } else { + None + } + } else { + None + }; + match selector { + Some(refine) => { + if REFINE_TOPIC[0..10] != refine { + continue; + } + } + None => { + continue; + } + } + let input = transaction.input.clone(); + let input: Option = if let Some(input) = input { + if let Ok(input) = prefix_hex::decode::>(&input) { + let data: Vec = input.iter().skip(4).copied().collect(); + Some(prefix_hex::encode(&data)) + } else { + None + } + } else { + None + }; events.push(Event { log: Log { block_hash: transaction.block_hash.clone(), block_number: transaction.block_number, log_index: -1, - address: transaction.contract_address.clone(), + address: transaction.to.clone(), transaction_index, transaction_hash: transaction.hash.clone(), - data: None, - topics: vec![], + data: input, + topics: vec![Some(REFINE_TOPIC.to_string())], removed: None, }, block: blocks.get(&block_number).cloned(), From 7f04a9207f11a47ba75baec5f482ebbce39037f8 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Tue, 14 May 2024 13:29:28 -0400 Subject: [PATCH 5/9] Pass query --- src/lib.rs | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 33c396f..c97244a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,12 +139,13 @@ impl HypersyncClient { let rx = self .inner - .stream::(query, config) + .stream::(query.clone(), config) .await .context("start stream")?; Ok(EventsStream { inner: tokio::sync::Mutex::new(rx), + query, }) } @@ -294,12 +295,14 @@ impl HypersyncClient { }) .collect(); + let original_query = query.clone(); let res = self .inner .send::(&query) .await .context("execute query")?; - let res = convert_response_to_events(res).context("convert response to js format")?; + let res = convert_response_to_events(res, &original_query) + .context("convert response to js format")?; Ok(res) } @@ -464,6 +467,7 @@ impl QueryResponseStream { #[napi] pub struct EventsStream { inner: tokio::sync::Mutex>>, + query: skar_net_types::Query, } #[napi] @@ -476,12 +480,10 @@ impl EventsStream { } async fn recv_impl(&self) -> Option> { - self.inner - .lock() - .await - .recv() - .await - .map(|resp| convert_response_to_events(resp?).context("convert response")) + self.inner.lock().await.recv().await.map(|resp| { + let query = self.query.clone(); + convert_response_to_events(resp?, &query).context("convert response") + }) } } @@ -565,7 +567,10 @@ pub struct Events { pub rollback_guard: Option, } -fn convert_response_to_events(res: skar_client::QueryResponse) -> Result { +fn convert_response_to_events( + res: skar_client::QueryResponse, + query: &skar_net_types::Query, +) -> Result { let mut blocks = BTreeMap::new(); for batch in res.data.blocks.iter() { @@ -598,9 +603,7 @@ fn convert_response_to_events(res: skar_client::QueryResponse) -> Result let mut events = Vec::with_capacity(logs.len()); for log in logs.into_iter() { - let transaction = txs - .remove(&(log.block_number, log.transaction_index)) - .clone(); + let transaction = txs.get(&(log.block_number, log.transaction_index)).cloned(); let block = blocks.get(&log.block_number).cloned(); events.push(Event { @@ -610,26 +613,28 @@ fn convert_response_to_events(res: skar_client::QueryResponse) -> Result }) } + let matches: Vec<[u8; 4]> = query + .transactions + .iter() + .flat_map(|item| item.sighash.iter().map(|v: &FixedSizeData<4>| v.map(|v| v))) + .collect(); for ((block_number, transaction_index), transaction) in txs.into_iter() { let selector = transaction.input.clone(); - let selector: Option = if let Some(selector) = selector { + let selector: Option<[u8; 4]> = if let Some(selector) = selector { if selector.len() >= 4 { - Some(selector[0..10].to_string()) + if let Ok(decoded) = prefix_hex::decode::<[u8; 4]>(&selector[0..10]) { + Some(decoded) + } else { + None + } } else { None } } else { None }; - match selector { - Some(refine) => { - if REFINE_TOPIC[0..10] != refine { - continue; - } - } - None => { - continue; - } + if matches.is_empty() || !matches.contains(&selector.unwrap_or_default()) { + continue; } let input = transaction.input.clone(); let input: Option = if let Some(input) = input { From b0cc2f8569768da816ffafb52fdd1ed6eb5a7222 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Tue, 14 May 2024 16:20:21 -0400 Subject: [PATCH 6/9] fix: Remove logging --- patch/skar-client-0.16.3/tests/api_test.rs | 2 - src/lib.rs | 113 +++++++-------------- 2 files changed, 35 insertions(+), 80 deletions(-) diff --git a/patch/skar-client-0.16.3/tests/api_test.rs b/patch/skar-client-0.16.3/tests/api_test.rs index 31b5114..9a5a917 100644 --- a/patch/skar-client-0.16.3/tests/api_test.rs +++ b/patch/skar-client-0.16.3/tests/api_test.rs @@ -152,8 +152,6 @@ async fn test_api_decode_logs() { let decoded_logs = decoder.decode_logs(&res.data.logs).unwrap().unwrap(); assert_eq!(decoded_logs.len(), 1); - - println!("{:?}", decoded_logs[0]); } const URL: &str = "https://eth.hypersync.xyz"; diff --git a/src/lib.rs b/src/lib.rs index c97244a..8f73b34 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,23 +72,49 @@ impl HypersyncClient { .map_err(|e| napi::Error::from_reason(format!("{:?}", e))) } - async fn stream_impl(&self, query: Query, config: StreamConfig) -> Result { - let mut query = query.try_convert().context("parse query")?; - let config = config.try_convert().context("parse config")?; + fn mutate_query(&self, query: &mut skar_net_types::Query) { + let mut transactions = Vec::::new(); // 0x0000... is a special address that means no address query.logs = query .logs - .into_iter() + .iter() .map(|log| { - let mut log = log; + let mut log = log.clone(); let address = log.address.clone(); if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { log.address = vec![]; + } else { + let topics = log.topics.clone(); + let sighash: Option>> = topics.first().cloned(); + if let Some(sighash) = sighash { + let sighash = sighash + .iter() + .map(|v| { + let mut data = [0u8; 4]; + data.copy_from_slice(&v.as_slice()[0..4]); + FixedSizeData::from(data) + }) + .collect(); + transactions.push(TransactionSelection { + to: log.address.clone(), + from: vec![], + sighash, + status: None, + }); + }; } log }) .collect(); + query.transactions = transactions; + } + + async fn stream_impl(&self, query: Query, config: StreamConfig) -> Result { + let mut query = query.try_convert().context("parse query")?; + let config = config.try_convert().context("parse config")?; + + self.mutate_query(&mut query); let rx = self .inner @@ -123,19 +149,7 @@ impl HypersyncClient { let mut query = query.try_convert().context("parse query")?; let config = config.try_convert().context("parse config")?; - // 0x0000... is a special address that means no address - query.logs = query - .logs - .into_iter() - .map(|log| { - let mut log = log; - let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { - log.address = vec![]; - } - log - }) - .collect(); + self.mutate_query(&mut query); let rx = self .inner @@ -167,19 +181,7 @@ impl HypersyncClient { let mut query = query.try_convert().context("parse query")?; let config = config.try_convert().context("parse parquet config")?; - // 0x0000... is a special address that means no address - query.logs = query - .logs - .into_iter() - .map(|log| { - let mut log = log; - let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { - log.address = vec![]; - } - log - }) - .collect(); + self.mutate_query(&mut query); self.inner .create_parquet_folder(query, config) @@ -202,19 +204,7 @@ impl HypersyncClient { async fn send_req_impl(&self, query: Query) -> Result { let mut query = query.try_convert().context("parse query")?; - // 0x0000... is a special address that means no address - query.logs = query - .logs - .into_iter() - .map(|log| { - let mut log = log; - let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { - log.address = vec![]; - } - log - }) - .collect(); + self.mutate_query(&mut query); let res = self .inner @@ -260,40 +250,7 @@ impl HypersyncClient { } } - let mut transactions = Vec::::new(); - - // 0x0000... is a special address that means no address - query.logs = query - .logs - .into_iter() - .map(|log| { - let mut log = log; - let address = log.address.clone(); - if address.into_iter().all(|v| v.as_ref()[0..19] == [0u8; 19]) { - log.address = vec![]; - } else { - let topics = log.topics.clone(); - let sighash: Option>> = topics.first().cloned(); - if let Some(sighash) = sighash { - let sighash = sighash - .iter() - .map(|v| { - let mut data = [0u8; 4]; - data.copy_from_slice(&v.as_slice()[0..4]); - FixedSizeData::from(data) - }) - .collect(); - transactions.push(TransactionSelection { - to: log.address.clone(), - from: vec![], - sighash, - status: None, - }); - }; - } - log - }) - .collect(); + self.mutate_query(&mut query); let original_query = query.clone(); let res = self From 403e72e789e4e385f2ac7ae67939bbc63dcf8ddf Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Thu, 16 May 2024 04:37:58 -0400 Subject: [PATCH 7/9] fix: Cleanup --- src/lib.rs | 64 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8f73b34..ea12cba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -506,7 +506,6 @@ pub struct QueryResponse { const BLOCK_JOIN_FIELDS: &[&str] = &["number"]; const TX_JOIN_FIELDS: &[&str] = &["block_number", "transaction_index"]; const LOG_JOIN_FIELDS: &[&str] = &["log_index", "transaction_index", "block_number"]; -const REFINE_TOPIC: &str = "0xea2555830810ebb32141e4d1bde9d6fe2497e7fbefadad253cc27c9721240fe3"; #[napi(object)] pub struct Events { @@ -575,6 +574,18 @@ fn convert_response_to_events( .iter() .flat_map(|item| item.sighash.iter().map(|v: &FixedSizeData<4>| v.map(|v| v))) .collect(); + + let map: BTreeMap<[u8; 4], String> = matches + .iter() + .filter_map(|v| { + let full_topic = query + .logs + .iter() + .find_map(|l| l.topics[0].iter().find(|u| u[0..4] == *v)); + full_topic.map(|full_topic| (*v, prefix_hex::encode(full_topic.to_vec()))) + }) + .collect(); + for ((block_number, transaction_index), transaction) in txs.into_iter() { let selector = transaction.input.clone(); let selector: Option<[u8; 4]> = if let Some(selector) = selector { @@ -593,32 +604,35 @@ fn convert_response_to_events( if matches.is_empty() || !matches.contains(&selector.unwrap_or_default()) { continue; } - let input = transaction.input.clone(); - let input: Option = if let Some(input) = input { - if let Ok(input) = prefix_hex::decode::>(&input) { - let data: Vec = input.iter().skip(4).copied().collect(); - Some(prefix_hex::encode(&data)) + let full_topic = map.get(&selector.unwrap_or_default()).cloned(); + if let Some(full_topic) = full_topic { + let input = transaction.input.clone(); + let input: Option = if let Some(input) = input { + if let Ok(input) = prefix_hex::decode::>(&input) { + let data: Vec = input.iter().skip(4).copied().collect(); + Some(prefix_hex::encode(&data)) + } else { + None + } } else { None - } - } else { - None - }; - events.push(Event { - log: Log { - block_hash: transaction.block_hash.clone(), - block_number: transaction.block_number, - log_index: -1, - address: transaction.to.clone(), - transaction_index, - transaction_hash: transaction.hash.clone(), - data: input, - topics: vec![Some(REFINE_TOPIC.to_string())], - removed: None, - }, - block: blocks.get(&block_number).cloned(), - transaction: Some(transaction), - }) + }; + events.push(Event { + log: Log { + block_hash: transaction.block_hash.clone(), + block_number: transaction.block_number, + log_index: -1, + address: transaction.to.clone(), + transaction_index, + transaction_hash: transaction.hash.clone(), + data: input, + topics: vec![Some(full_topic)], + removed: None, + }, + block: blocks.get(&block_number).cloned(), + transaction: Some(transaction), + }) + } } Ok(Events { From eea0f7b7a51d36c58e22652a121c698f3d9f3c74 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Thu, 16 May 2024 07:51:29 -0400 Subject: [PATCH 8/9] fix: Use transaction_index instead of log_index for fn calls. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ea12cba..689aa7f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -621,7 +621,7 @@ fn convert_response_to_events( log: Log { block_hash: transaction.block_hash.clone(), block_number: transaction.block_number, - log_index: -1, + log_index: transaction_index, address: transaction.to.clone(), transaction_index, transaction_hash: transaction.hash.clone(), From 561e8ad060b69dac0a33debc3f8171f31acf1949 Mon Sep 17 00:00:00 2001 From: Andreas Richter <708186+richtera@users.noreply.github.com> Date: Fri, 18 Jul 2025 14:28:20 -0400 Subject: [PATCH 9/9] fix: Repair missing Cargo.lock --- .gitignore | 1 - Cargo.lock | 3687 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3687 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 18eadbd..c973144 100644 --- a/.gitignore +++ b/.gitignore @@ -184,7 +184,6 @@ $RECYCLE.BIN/ #Added by cargo /target -Cargo.lock .pnp.* .yarn/* diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..869a5af --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3687 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.3", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2919acdad13336bc5dc26b636cdd6892c2f27fb0d4a58320a00c2713cf6a4e9a" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.26", +] + +[[package]] +name = "alloy-json-abi" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ed0f2a6c3a1c947b4508522a53a190dba8f94dcd4e3e1a5af945a498e78f2f" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-primitives" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand 0.8.5", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +dependencies = [ + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" +dependencies = [ + "const-hex", + "dunce", + "heck", + "indexmap 2.10.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.104", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0045cc89524e1451ccf33e8581355b6027ac7c6e494bb02959d4213ad0d8e91d" +dependencies = [ + "winnow 0.6.26", +] + +[[package]] +name = "alloy-sol-types" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" +dependencies = [ + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "array-init-cursor" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed51fe0f224d1d4ea768be38c51f9f831dee9d05c163c11fba0b8c44387b1fc3" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + +[[package]] +name = "arrow-format" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07884ea216994cdc32a2d5f8274a8bee979cfe90274b83f86f440866ee3132c7" +dependencies = [ + "planus", + "serde", +] + +[[package]] +name = "arrow2" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963fef509b757bcbbf9e5ffa23bcb345614d99f4f6f531f97417b27b8604d389" +dependencies = [ + "ahash", + "arrow-format", + "base64", + "bytemuck", + "chrono", + "dyn-clone", + "either", + "ethnum", + "fallible-streaming-iterator", + "foreign_vec", + "futures", + "getrandom 0.2.16", + "hash_hasher", + "hashbrown 0.14.5", + "indexmap 1.9.3", + "json-deserializer", + "lexical-core", + "lz4", + "num-traits", + "parquet2", + "rustc_version 0.4.1", + "simdutf8", + "streaming-iterator", + "zstd", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "bytemuck" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] + +[[package]] +name = "capnp" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e985a566bdaae9a428a957d12b10c318d41b2afddb54cfbb764878059df636e" +dependencies = [ + "embedded-io", +] + +[[package]] +name = "capnpc" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ba30e0f08582d53c2f3710cf4bb65ff562614b1ba86906d7391adffe189ec" +dependencies = [ + "capnp", +] + +[[package]] +name = "cc" +version = "1.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "const-hex" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e22e0ed40b96a48d3db274f72fd365bd78f67af39b6bbd47e8a15e1c6207ff" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +dependencies = [ + "quote", + "syn 2.0.104", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.104", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "envio_hypersync-client" +version = "0.0.0" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "anyhow", + "arrayvec", + "arrow2", + "env_logger", + "faster-hex", + "napi", + "napi-build", + "napi-derive", + "prefix-hex", + "serde", + "serde_json", + "skar-client", + "skar-format", + "skar-net-types", + "tokio", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "ethnum" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "faster-hex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" +dependencies = [ + "serde", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fastrange-rs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e90a1392cd6ec5ebe42ccaf251f2b7ba6be654c377f05c913f3898bfb2172512" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.10.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash_hasher" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b4b9ebce26001bad2e6366295f64e381c1e9c479109202149b9e15e154973e9" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", +] + +[[package]] +name = "io-uring" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +dependencies = [ + "bitflags 2.9.1", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json-deserializer" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f63b421e16eb4100beb677af56f0b4f3a4f08bab74ef2af079ce5bb92c2683f" +dependencies = [ + "indexmap 1.9.3", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lexical-core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" +dependencies = [ + "lexical-parse-integer", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-parse-integer" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-util" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lexical-write-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] + +[[package]] +name = "lexical-write-integer" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.2", +] + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "lz4" +version = "1.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" +dependencies = [ + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "napi" +version = "2.16.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55740c4ae1d8696773c78fdafd5d0e5fe9bc9f1b071c7ba493ba5c413a9184f3" +dependencies = [ + "bitflags 2.9.1", + "ctor", + "napi-derive", + "napi-sys", + "once_cell", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "napi-build" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff539e61c5e3dd4d7d283610662f5d672c2aea0f158df78af694f13dbb3287b" + +[[package]] +name = "napi-derive" +version = "2.16.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c" +dependencies = [ + "cfg-if", + "convert_case 0.6.0", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf" +dependencies = [ + "convert_case 0.6.0", + "once_cell", + "proc-macro2", + "quote", + "regex", + "semver 1.0.26", + "syn 2.0.104", +] + +[[package]] +name = "napi-sys" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3" +dependencies = [ + "libloading", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "parquet-format-safe" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1131c54b167dd4e4799ce762e1ab01549ebb94d5bdd13e6ec1b467491c378e1f" +dependencies = [ + "async-trait", + "futures", +] + +[[package]] +name = "parquet2" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579fe5745f02cef3d5f236bfed216fd4693e49e4e920a13475c6132233283bce" +dependencies = [ + "async-stream", + "brotli", + "flate2", + "futures", + "lz4", + "parquet-format-safe", + "seq-macro", + "snap", + "streaming-decompression", + "xxhash-rust", + "zstd", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +dependencies = [ + "memchr", + "thiserror 2.0.12", + "ucd-trie", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "planus" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1691dd09e82f428ce8d6310bd6d5da2557c82ff17694d2a32cad7242aea89f" +dependencies = [ + "array-init-cursor", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prefix-hex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1799f398371ad6957951ec446d3ff322d35c46d9db2e217b67e828b311c249" +dependencies = [ + "hex", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.9.1", + "lazy_static", + "num-traits", + "rand 0.9.1", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "ruint" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand 0.8.5", + "rand 0.9.1", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.26", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.60.2", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "skar-client" +version = "0.16.3" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "anyhow", + "arrayvec", + "arrow2", + "capnp", + "faster-hex", + "fastrange-rs", + "futures", + "log", + "num_cpus", + "parquet2", + "rand 0.8.5", + "rayon", + "reqwest", + "ruint", + "serde", + "serde_json", + "skar-format", + "skar-net-types", + "skar-schema", + "tokio", + "tokio-util", + "url", + "xxhash-rust", +] + +[[package]] +name = "skar-format" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a248a5fd84f9bc6e477f634afe0d32336a157b7f5c69ffe805909468b7b3c66e" +dependencies = [ + "arrayvec", + "derive_more", + "faster-hex", + "serde", + "thiserror 1.0.69", +] + +[[package]] +name = "skar-net-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e8c487850640607daecf59d5bea52d872e91b03d8ae482792847ec7d8ab3629" +dependencies = [ + "arrayvec", + "capnp", + "capnpc", + "serde", + "skar-format", +] + +[[package]] +name = "skar-schema" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e6ec948f32f41d3aed59d29b1c59156e362fefd35f0114532dee3c87723f548" +dependencies = [ + "anyhow", + "arrow2", +] + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "snap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "streaming-decompression" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3" +dependencies = [ + "fallible-streaming-iterator", +] + +[[package]] +name = "streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "pin-project-lite", + "slab", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap 2.10.0", + "toml_datetime", + "winnow 0.7.12", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", +]