From d79ff9e3acd08b868da31a8fc79b05ac0475568b Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Fri, 10 May 2024 22:29:16 +0200 Subject: [PATCH 01/16] Create chain struct, placeholder contracts - chain struct that allows specification of custom optional rpc url --- .gitignore | 2 + Cargo.lock | 110 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 7 +++ src/chains/contracts.rs | 16 ++++++ src/chains/mod.rs | 87 +++++++++++++++++++++++++++++++ src/fetcher/mod.rs | 0 src/lib.rs | 2 + 7 files changed, 224 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/chains/contracts.rs create mode 100644 src/chains/mod.rs create mode 100644 src/fetcher/mod.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5a2e450 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0aca722 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,110 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustlink" +version = "0.1.0" +dependencies = [ + "tokio", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "pin-project-lite", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..374bf23 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rustlink" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = "1.37.0" diff --git a/src/chains/contracts.rs b/src/chains/contracts.rs new file mode 100644 index 0000000..5dcd607 --- /dev/null +++ b/src/chains/contracts.rs @@ -0,0 +1,16 @@ +// contracts.rs +use std::collections::HashMap; + +pub fn ethereum_contracts() -> HashMap<&'static str, &'static str> { + let mut map = HashMap::new(); + map.insert("BTC", "0xabcd1234efgh5678ijkl9012mnop3456qrst7890"); + map.insert("ETH", "0x1234abcd5678efgh9012ijkl3456mnop7890qrst"); + map +} + +pub fn arbitrum_contracts() -> HashMap<&'static str, &'static str> { + let mut map = HashMap::new(); + map.insert("LINK", "0x1234abcd5678efgh9012ijkl3456mnop7890qrst"); + map.insert("DAI", "0xabcd1234efgh5678ijkl9012mnop3456qrst7890"); + map +} diff --git a/src/chains/mod.rs b/src/chains/mod.rs new file mode 100644 index 0000000..b7486fa --- /dev/null +++ b/src/chains/mod.rs @@ -0,0 +1,87 @@ + +mod contracts; +use std::collections::HashMap; + +use self::contracts::{arbitrum_contracts, ethereum_contracts}; + + +enum Chain { + Ethereum { + rpc_url: Option<&'static str>, + contracts: HashMap<&'static str, &'static str>, + }, + ArbitrumOne { + rpc_url: Option<&'static str>, + contracts: HashMap<&'static str, &'static str>, + } +} + +/// Chain presets for rustlink. +/// Available networks: +/// - Ethereum (chain id: 1) +/// - ArbitrumOne (chain id: 42161) +/// +/// Usage: +/// +/// **Using fallback RPC** +/// ```rust +/// Chain::new(1,None) +/// ``` +/// +/// **Using custom RPC url** +/// ```rust +/// Chain::new(1,"https://1rpc.io") +/// ``` +impl Chain{ + /// Create a new chain instance optionally specifying a custom rpc url + pub fn new(chain_id: u32,rpc_url: Option<&'static str>,) -> Self { + let contracts = match chain_id { + 1 => ethereum_contracts(), + 42161 => arbitrum_contracts(), + _ => HashMap::new(), + }; + + match chain_id { + 1 => Chain::Ethereum { rpc_url, contracts }, + 42161 => Chain::ArbitrumOne { rpc_url, contracts }, + _ => unreachable!(), // Assuming these are the only options + } + } + + /// Return the RPC url of this chain. + pub fn rpc_url(&self) -> &str { + match self { + Chain::Ethereum { rpc_url: Some(url), .. } => url, + Chain::Ethereum { rpc_url: None, .. } => "https://1rpc.io/eth", + + Chain::ArbitrumOne { rpc_url: Some(url), .. } => url, + Chain::ArbitrumOne { rpc_url: None, .. } => "https://1rpc.io/arb", + } + } + + /// Returns a reference to the contracts map for the given chain instance. + /// If no contracts exist for the chain, returns an empty HashMap. + pub fn contracts(&self) -> &HashMap<&'static str, &'static str> { + match self { + Chain::Ethereum { contracts, .. } => contracts, + Chain::ArbitrumOne { contracts, .. } => contracts, + } + } + + + +} +#[cfg(test)] +mod tests { + use crate::chains::Chain; + + #[test] + fn valid_networks(){ + assert!(Chain::new(1,None).rpc_url().contains("https://")); + assert!(Chain::new(42161,None).rpc_url().contains("https://")); + + + } + +} + diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e6468f8 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod chains; +pub mod fetcher; \ No newline at end of file From 5b515341757ea1a881dceff1214e4a8922331bc6 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Sat, 11 May 2024 01:17:39 +0200 Subject: [PATCH 02/16] Finalized rustlink struct - setup logging - setup sled --- Cargo.lock | 3278 ++++++++++++++++++++++++++++++++++++++- Cargo.toml | 7 +- src/chains/contracts.rs | 12 +- src/chains/mod.rs | 39 +- src/core/fetcher.rs | 1 + src/core/mod.rs | 70 + src/fetcher/mod.rs | 0 src/lib.rs | 2 +- 8 files changed, 3333 insertions(+), 76 deletions(-) create mode 100644 src/core/fetcher.rs create mode 100644 src/core/mod.rs delete mode 100644 src/fetcher/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 0aca722..178d626 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,93 +18,3287 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "backtrace" -version = "0.3.71" +name = "ahash" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "addr2line", - "cc", "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "once_cell", + "version_check", + "zerocopy", ] [[package]] -name = "cc" -version = "1.0.97" +name = "allocator-api2" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "alloy" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-wallet", + "alloy-transport", + "alloy-transport-http", + "reqwest", +] + +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "thiserror", +] + +[[package]] +name = "alloy-core" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "e30b83573b348305b9629a094b5331093a030514cd5713433799495cb283fea1" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] [[package]] -name = "gimli" -version = "0.28.1" +name = "alloy-dyn-abi" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "545885d9b0b2c30fd344ae291439b4bfe59e48dd62fbc862f8503d98088967dc" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.8", +] [[package]] -name = "libc" -version = "0.2.154" +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "once_cell", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-primitives", + "alloy-serde", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-abi" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "786689872ec4e7d354810ab0dffd48bb40b838c047522eb031cbd47d15634849" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] [[package]] -name = "memchr" -version = "2.7.2" +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "futures-utils-wasm", + "thiserror", +] + +[[package]] +name = "alloy-primitives" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] [[package]] -name = "miniz_oxide" +name = "alloy-provider" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-rpc-types-trace", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "futures-utils-wasm", + "lru", + "reqwest", + "serde_json", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-rpc-types-trace" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types", + "alloy-serde", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-signer-wallet" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand", + "thiserror", +] + +[[package]] +name = "alloy-sol-macro" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "89c80a2cb97e7aa48611cbb63950336f9824a174cdf670527cc6465078a26ea1" dependencies = [ - "adler", + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck 0.4.1", + "indexmap", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.61", + "syn-solidity", + "tiny-keccak", ] [[package]] -name = "object" -version = "0.32.2" +name = "alloy-sol-macro-input" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "c58894b58ac50979eeac6249661991ac40b9d541830d9a725f7714cc9ef08c23" dependencies = [ - "memchr", + "alloy-json-abi", + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.61", + "syn-solidity", ] [[package]] -name = "pin-project-lite" -version = "0.2.14" +name = "alloy-sol-type-parser" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "7da8e71ea68e780cc203919e03f69f59e7afe92d2696fb1dcb6662f61e4031b6" +dependencies = [ + "winnow 0.6.8", +] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "alloy-sol-types" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "399287f68d1081ed8b1f4903c49687658b95b142207d7cb4ae2f4813915343ef" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] [[package]] -name = "rustlink" +name = "alloy-transport" version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" dependencies = [ + "alloy-json-rpc", + "base64", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", "tokio", + "tower", + "url", + "wasm-bindgen-futures", ] [[package]] -name = "tokio" -version = "1.37.0" +name = "alloy-transport-http" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "backtrace", + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" + +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[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 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "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", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", "pin-project-lite", ] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[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 = "blst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "serde", +] + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets 0.52.5", +] + +[[package]] +name = "const-hex" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +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 = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[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.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[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", + "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 = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "destructure_traitobject" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" + +[[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 = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[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.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[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", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[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 = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[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 = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[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.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[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 = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", +] + +[[package]] +name = "keccak-asm" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +dependencies = [ + "serde", +] + +[[package]] +name = "log-mdc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" + +[[package]] +name = "log4rs" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0816135ae15bd0391cf284eab37e6e3ee0a6ee63d2ceeb659862bd8d0a984ca6" +dependencies = [ + "anyhow", + "arc-swap", + "chrono", + "derivative", + "fnv", + "humantime", + "libc", + "log", + "log-mdc", + "once_cell", + "parking_lot 0.12.2", + "rand", + "serde", + "serde-value", + "serde_json", + "serde_yaml", + "thiserror", + "thread-id", + "typemap-ors", + "winapi", +] + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[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.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.10", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.1", + "smallvec", + "windows-targets 0.52.5", +] + +[[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.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[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.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +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.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.5.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "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.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[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", + "rand_core", +] + +[[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", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "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 = "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.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustlink" +version = "0.1.0" +dependencies = [ + "alloy", + "log", + "log4rs", + "reqwest", + "sled", + "tokio", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[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.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[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 = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[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.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "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 = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3-asm" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[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", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +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 = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[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.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa0cefd02f532035d83cfec82647c6eb53140b0485220760e669f4bad489e36" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[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.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "thread-id" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0ec81c46e9eb50deaa257be2f148adf052d1fb7701cfd55ccfab2525280b70b" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot 0.12.2", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +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 = "typemap-ors" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68c24b707f02dd18f1e4ccceb9d49f2058c2fb86384ef9972592904d7a28867" +dependencies = [ + "unsafe-any-ors", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[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-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unsafe-any-ors" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a303d30665362d9680d7d91d78b23f5f899504d4f08b3c4cf08d055d87c0ad" +dependencies = [ + "destructure_traitobject", +] + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +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.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.61", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[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.5", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +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.61", +] diff --git a/Cargo.toml b/Cargo.toml index 374bf23..cfda692 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -tokio = "1.37.0" +log = "0.4.21" +log4rs = "1.3.0" +sled = "0.34.7" +tokio = {version="1.37.0",features=["full"]} +alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0",features=["rpc-types-eth","eips","signers","signer-wallet","consensus","network","providers","transports","transport-http","contract"] } +reqwest = "0.12.4" diff --git a/src/chains/contracts.rs b/src/chains/contracts.rs index 5dcd607..9b9bc46 100644 --- a/src/chains/contracts.rs +++ b/src/chains/contracts.rs @@ -1,16 +1,16 @@ // contracts.rs use std::collections::HashMap; -pub fn ethereum_contracts() -> HashMap<&'static str, &'static str> { +pub fn ethereum_contracts() -> HashMap { let mut map = HashMap::new(); - map.insert("BTC", "0xabcd1234efgh5678ijkl9012mnop3456qrst7890"); - map.insert("ETH", "0x1234abcd5678efgh9012ijkl3456mnop7890qrst"); + map.insert("BTC".to_string(), "0xabcd1234efgh5678ijkl9012mnop3456qrst7890".to_string()); + map.insert("ETH".to_string(), "0x1234abcd5678efgh9012ijkl3456mnop7890qrst".to_string()); map } -pub fn arbitrum_contracts() -> HashMap<&'static str, &'static str> { +pub fn arbitrum_contracts() -> HashMap { let mut map = HashMap::new(); - map.insert("LINK", "0x1234abcd5678efgh9012ijkl3456mnop7890qrst"); - map.insert("DAI", "0xabcd1234efgh5678ijkl9012mnop3456qrst7890"); + map.insert("BTC".to_string(), "0xabcd1234efgh5678ijkl9012mnop3456qrst7890".to_string()); + map.insert("ETH".to_string(), "0x1234abcd5678efgh9012ijkl3456mnop7890qrst".to_string()); map } diff --git a/src/chains/mod.rs b/src/chains/mod.rs index b7486fa..277a483 100644 --- a/src/chains/mod.rs +++ b/src/chains/mod.rs @@ -5,14 +5,14 @@ use std::collections::HashMap; use self::contracts::{arbitrum_contracts, ethereum_contracts}; -enum Chain { +pub enum Chain { Ethereum { - rpc_url: Option<&'static str>, - contracts: HashMap<&'static str, &'static str>, + rpc_url: String, + contracts: HashMap, }, ArbitrumOne { - rpc_url: Option<&'static str>, - contracts: HashMap<&'static str, &'static str>, + rpc_url: String, + contracts: HashMap, } } @@ -23,18 +23,12 @@ enum Chain { /// /// Usage: /// -/// **Using fallback RPC** -/// ```rust -/// Chain::new(1,None) -/// ``` -/// -/// **Using custom RPC url** /// ```rust /// Chain::new(1,"https://1rpc.io") /// ``` impl Chain{ - /// Create a new chain instance optionally specifying a custom rpc url - pub fn new(chain_id: u32,rpc_url: Option<&'static str>,) -> Self { + /// Create a new chain instance specifying a custom rpc url + pub fn new(chain_id: u32,rpc_url: String,) -> Self { let contracts = match chain_id { 1 => ethereum_contracts(), 42161 => arbitrum_contracts(), @@ -49,27 +43,22 @@ impl Chain{ } /// Return the RPC url of this chain. - pub fn rpc_url(&self) -> &str { + pub fn rpc_url(&self) -> &String { match self { - Chain::Ethereum { rpc_url: Some(url), .. } => url, - Chain::Ethereum { rpc_url: None, .. } => "https://1rpc.io/eth", - - Chain::ArbitrumOne { rpc_url: Some(url), .. } => url, - Chain::ArbitrumOne { rpc_url: None, .. } => "https://1rpc.io/arb", + Chain::Ethereum { rpc_url: url, .. } => url, + Chain::ArbitrumOne { rpc_url: url, .. } => url, } } /// Returns a reference to the contracts map for the given chain instance. /// If no contracts exist for the chain, returns an empty HashMap. - pub fn contracts(&self) -> &HashMap<&'static str, &'static str> { + pub fn contracts(&self) -> &HashMap { match self { Chain::Ethereum { contracts, .. } => contracts, Chain::ArbitrumOne { contracts, .. } => contracts, } } - - } #[cfg(test)] mod tests { @@ -77,10 +66,8 @@ mod tests { #[test] fn valid_networks(){ - assert!(Chain::new(1,None).rpc_url().contains("https://")); - assert!(Chain::new(42161,None).rpc_url().contains("https://")); - - + assert!(Chain::new(1,"https://1rpc.io/eth".to_string()).rpc_url().contains("https://")); + assert!(Chain::new(42161,"https://1rpc.io/arb".to_string()).rpc_url().contains("https://")); } } diff --git a/src/core/fetcher.rs b/src/core/fetcher.rs new file mode 100644 index 0000000..c35afa8 --- /dev/null +++ b/src/core/fetcher.rs @@ -0,0 +1 @@ +//write the fetcher here \ No newline at end of file diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..188dc33 --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,70 @@ +use std::str::FromStr; + +use sled::Tree; + +use crate::chains::Chain; +use log4rs::{ + append::file::FileAppender, + config::{Appender, Root}, + encode::pattern::PatternEncoder, + Config, +}; +use log::LevelFilter; +use alloy::{ + primitives::{Address, U256}, + providers::{ProviderBuilder, RootProvider}, + signers::wallet::LocalWallet, + transports::http::Http, +}; +use reqwest::{Client, Url}; +pub struct RustlinkConfiguration { + pub chain:Chain, + pub fetch_interval_seconds:u64, + pub provider:RootProvider> +} + +pub struct Rustlink { + pub configuration:RustlinkConfiguration, + pub tree:Tree +} + +impl Rustlink { + pub fn new(chain:Chain,fetch_interval_seconds:u64,sled_path:&str)->Rustlink{ + let db=sled::open(sled_path).unwrap(); + let provider = ProviderBuilder::new().on_http(Url::from_str(chain.rpc_url()).unwrap()); + + // Setup logging + let logfile = FileAppender::builder() + .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) + .build("./rustlink.log") + .unwrap(); + + let config = Config::builder() + .appender(Appender::builder().build("logfile", Box::new(logfile))) + .build(Root::builder().appender("logfile").build(LevelFilter::Info)) + .unwrap(); + + // Try to initialize and catch error silently if already initialized + // during tests this make this function throw error + if log4rs::init_config(config).is_err() { + println!("Logger already initialized."); + } + + Rustlink { + configuration:RustlinkConfiguration{ + chain, + fetch_interval_seconds, + provider + }, + tree:db.open_tree("rustlink").unwrap() + } + + } + + pub fn fetch() { + //tokio::spawn(); + + } + +} + diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/lib.rs b/src/lib.rs index e6468f8..36e90c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,2 @@ pub mod chains; -pub mod fetcher; \ No newline at end of file +pub mod core; \ No newline at end of file From 65bb751422c4bca99599a6862f1998d320d347b0 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Mon, 13 May 2024 21:38:51 +0200 Subject: [PATCH 03/16] ABI, fetcher, contract abstraction This commit adds: - Chainlink aggregator ABI - Async price updater - Contract wrapper for chainlink contracts - Tests --- .gitignore | 2 +- Cargo.lock | 36 ++++-- Cargo.toml | 5 +- README.md | 4 +- src/abi/IAggregatorV3Interface.json | 113 +++++++++++++++++++ src/chains/contracts.rs | 16 --- src/chains/mod.rs | 74 ------------ src/core/fetcher.rs | 1 - src/core/mod.rs | 70 ------------ src/fetcher/mod.rs | 50 +++++++++ src/interface/mod.rs | 119 ++++++++++++++++++++ src/lib.rs | 168 +++++++++++++++++++++++++++- 12 files changed, 479 insertions(+), 179 deletions(-) create mode 100644 src/abi/IAggregatorV3Interface.json delete mode 100644 src/chains/contracts.rs delete mode 100644 src/chains/mod.rs delete mode 100644 src/core/fetcher.rs delete mode 100644 src/core/mod.rs create mode 100644 src/fetcher/mod.rs create mode 100644 src/interface/mod.rs diff --git a/.gitignore b/.gitignore index 5a2e450..5fc89cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ - /target +rustlink.log \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 178d626..29fc84c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -673,6 +673,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -900,6 +909,21 @@ dependencies = [ "typenum", ] +[[package]] +name = "cryptoprices" +version = "0.1.0" +dependencies = [ + "alloy", + "bincode", + "log", + "log4rs", + "reqwest", + "serde", + "sled", + "thiserror", + "tokio", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -2271,18 +2295,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustlink" -version = "0.1.0" -dependencies = [ - "alloy", - "log", - "log4rs", - "reqwest", - "sled", - "tokio", -] - [[package]] name = "rustls-pemfile" version = "2.1.2" diff --git a/Cargo.toml b/Cargo.toml index cfda692..5787d83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rustlink" +name = "cryptoprices" version = "0.1.0" edition = "2021" @@ -10,3 +10,6 @@ sled = "0.34.7" tokio = {version="1.37.0",features=["full"]} alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0",features=["rpc-types-eth","eips","signers","signer-wallet","consensus","network","providers","transports","transport-http","contract"] } reqwest = "0.12.4" +bincode = "1.3.3" +serde = "1.0.201" +thiserror = "1.0.60" diff --git a/README.md b/README.md index ad75fa5..aec9d69 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# rustlink - A rust library for periodically retrieving cryptocurrency prices from the ChainLink decentralized price feed. +# CryptoPrices + A lightweight rust library for periodically retrieving cryptocurrency prices from the ChainLink decentralized price feed. diff --git a/src/abi/IAggregatorV3Interface.json b/src/abi/IAggregatorV3Interface.json new file mode 100644 index 0000000..8c929c8 --- /dev/null +++ b/src/abi/IAggregatorV3Interface.json @@ -0,0 +1,113 @@ +[ + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/src/chains/contracts.rs b/src/chains/contracts.rs deleted file mode 100644 index 9b9bc46..0000000 --- a/src/chains/contracts.rs +++ /dev/null @@ -1,16 +0,0 @@ -// contracts.rs -use std::collections::HashMap; - -pub fn ethereum_contracts() -> HashMap { - let mut map = HashMap::new(); - map.insert("BTC".to_string(), "0xabcd1234efgh5678ijkl9012mnop3456qrst7890".to_string()); - map.insert("ETH".to_string(), "0x1234abcd5678efgh9012ijkl3456mnop7890qrst".to_string()); - map -} - -pub fn arbitrum_contracts() -> HashMap { - let mut map = HashMap::new(); - map.insert("BTC".to_string(), "0xabcd1234efgh5678ijkl9012mnop3456qrst7890".to_string()); - map.insert("ETH".to_string(), "0x1234abcd5678efgh9012ijkl3456mnop7890qrst".to_string()); - map -} diff --git a/src/chains/mod.rs b/src/chains/mod.rs deleted file mode 100644 index 277a483..0000000 --- a/src/chains/mod.rs +++ /dev/null @@ -1,74 +0,0 @@ - -mod contracts; -use std::collections::HashMap; - -use self::contracts::{arbitrum_contracts, ethereum_contracts}; - - -pub enum Chain { - Ethereum { - rpc_url: String, - contracts: HashMap, - }, - ArbitrumOne { - rpc_url: String, - contracts: HashMap, - } -} - -/// Chain presets for rustlink. -/// Available networks: -/// - Ethereum (chain id: 1) -/// - ArbitrumOne (chain id: 42161) -/// -/// Usage: -/// -/// ```rust -/// Chain::new(1,"https://1rpc.io") -/// ``` -impl Chain{ - /// Create a new chain instance specifying a custom rpc url - pub fn new(chain_id: u32,rpc_url: String,) -> Self { - let contracts = match chain_id { - 1 => ethereum_contracts(), - 42161 => arbitrum_contracts(), - _ => HashMap::new(), - }; - - match chain_id { - 1 => Chain::Ethereum { rpc_url, contracts }, - 42161 => Chain::ArbitrumOne { rpc_url, contracts }, - _ => unreachable!(), // Assuming these are the only options - } - } - - /// Return the RPC url of this chain. - pub fn rpc_url(&self) -> &String { - match self { - Chain::Ethereum { rpc_url: url, .. } => url, - Chain::ArbitrumOne { rpc_url: url, .. } => url, - } - } - - /// Returns a reference to the contracts map for the given chain instance. - /// If no contracts exist for the chain, returns an empty HashMap. - pub fn contracts(&self) -> &HashMap { - match self { - Chain::Ethereum { contracts, .. } => contracts, - Chain::ArbitrumOne { contracts, .. } => contracts, - } - } - -} -#[cfg(test)] -mod tests { - use crate::chains::Chain; - - #[test] - fn valid_networks(){ - assert!(Chain::new(1,"https://1rpc.io/eth".to_string()).rpc_url().contains("https://")); - assert!(Chain::new(42161,"https://1rpc.io/arb".to_string()).rpc_url().contains("https://")); - } - -} - diff --git a/src/core/fetcher.rs b/src/core/fetcher.rs deleted file mode 100644 index c35afa8..0000000 --- a/src/core/fetcher.rs +++ /dev/null @@ -1 +0,0 @@ -//write the fetcher here \ No newline at end of file diff --git a/src/core/mod.rs b/src/core/mod.rs deleted file mode 100644 index 188dc33..0000000 --- a/src/core/mod.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::str::FromStr; - -use sled::Tree; - -use crate::chains::Chain; -use log4rs::{ - append::file::FileAppender, - config::{Appender, Root}, - encode::pattern::PatternEncoder, - Config, -}; -use log::LevelFilter; -use alloy::{ - primitives::{Address, U256}, - providers::{ProviderBuilder, RootProvider}, - signers::wallet::LocalWallet, - transports::http::Http, -}; -use reqwest::{Client, Url}; -pub struct RustlinkConfiguration { - pub chain:Chain, - pub fetch_interval_seconds:u64, - pub provider:RootProvider> -} - -pub struct Rustlink { - pub configuration:RustlinkConfiguration, - pub tree:Tree -} - -impl Rustlink { - pub fn new(chain:Chain,fetch_interval_seconds:u64,sled_path:&str)->Rustlink{ - let db=sled::open(sled_path).unwrap(); - let provider = ProviderBuilder::new().on_http(Url::from_str(chain.rpc_url()).unwrap()); - - // Setup logging - let logfile = FileAppender::builder() - .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) - .build("./rustlink.log") - .unwrap(); - - let config = Config::builder() - .appender(Appender::builder().build("logfile", Box::new(logfile))) - .build(Root::builder().appender("logfile").build(LevelFilter::Info)) - .unwrap(); - - // Try to initialize and catch error silently if already initialized - // during tests this make this function throw error - if log4rs::init_config(config).is_err() { - println!("Logger already initialized."); - } - - Rustlink { - configuration:RustlinkConfiguration{ - chain, - fetch_interval_seconds, - provider - }, - tree:db.open_tree("rustlink").unwrap() - } - - } - - pub fn fetch() { - //tokio::spawn(); - - } - -} - diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs new file mode 100644 index 0000000..b2a3fe2 --- /dev/null +++ b/src/fetcher/mod.rs @@ -0,0 +1,50 @@ +use super::{ + interface::{ChainlinkContract, PriceData, Serializable}, + Configuration, CryptoPrices, +}; + +/// Retrieves the price of an underlying asset from a particular contract +async fn fetch_price_for_contract( + rustlink_configuration: Configuration, + address: &str, +) -> Result { + let contract = ChainlinkContract::new(rustlink_configuration.provider, address).await?; + contract.get_price().await +} + +/// A task that continously fetches cryptocurrency prices from Chainlink decentralised price data feed. +pub async fn fetch_prices(crypto_prices: CryptoPrices) { + let contracts = &crypto_prices.configuration.contracts; + loop { + for contract_configuration in contracts { + let symbol = &contract_configuration.0; + let address = &contract_configuration.1; + match fetch_price_for_contract(crypto_prices.clone().configuration, address).await { + Ok(price_data) => { + match crypto_prices + .tree + .insert(symbol, price_data.to_bin().unwrap()) + { + Ok(_) => {} + Err(error) => { + log::error!("Could not update price in db: {}", error); + } + } + } + Err(error) => { + log::error!("Could not fetch price: {}", error); + } + } + tokio::time::sleep(std::time::Duration::from_secs( + crypto_prices.configuration.fetch_interval_seconds, + )) + .await; + } + + // Give back control to tokio runtime. + tokio::time::sleep(std::time::Duration::from_secs( + crypto_prices.configuration.fetch_interval_seconds, + )) + .await; + } +} diff --git a/src/interface/mod.rs b/src/interface/mod.rs new file mode 100644 index 0000000..a81a5d4 --- /dev/null +++ b/src/interface/mod.rs @@ -0,0 +1,119 @@ +use alloy::{contract::Error, providers::RootProvider, sol, transports::http::Http}; +use reqwest::Client; +use serde::{Deserialize, Serialize}; + +use self::IAggregatorV3Interface::IAggregatorV3InterfaceInstance; + +sol!( + #[allow(missing_docs)] + #[sol(rpc)] + IAggregatorV3Interface, + "src/abi/IAggregatorV3Interface.json" +); + +pub trait Serializable { + fn to_bin(&self) -> Result, Box>; + fn from_bin(data: Vec) -> Result> + where + Self: Sized; +} + +#[derive(Clone)] +pub struct ChainlinkContract { + pub contract: IAggregatorV3InterfaceInstance, RootProvider>>, + pub decimals: u8, +} + +/// The latest price received for this symbol. +/// This data is directly retrieved from the underlying contract. +#[derive(Deserialize, Serialize)] +pub struct PriceData { + /// Id of the submission by the aggregator + pub round_id: u128, + /// Answered in round + pub answered_in_round: u128, + /// Timestamp for when the aggregator started collecting data + pub started_at: String, + /// Timestamp for when the aggregator posted the price update + pub updated_at: String, + /// Price of the asset + pub price: f64, +} + +impl Serializable for PriceData { + /// Serializes invoice to bytes + fn to_bin(&self) -> Result, Box> { + bincode::serialize(&self) + } + + /// Deserializes invoice from bytes + fn from_bin(data: Vec) -> Result> { + bincode::deserialize(&data) + } +} + +impl ChainlinkContract { + /// Creates a new instance of a chainlink price aggregator. This is just a wrapper + /// function to simplify the interactions with the contract. + pub async fn new( + provider: RootProvider>, + contract_address: &str, + ) -> Result { + let contract = IAggregatorV3Interface::new(contract_address.parse().unwrap(), provider); + + let IAggregatorV3Interface::decimalsReturn { _0: decimals } = + contract.decimals().call().await?; + Ok(ChainlinkContract { contract, decimals }) + } + + /// Retrieves the latest price of this underlying asset + /// from the chainlink decentralized data feed + pub async fn get_price(&self) -> Result { + let IAggregatorV3Interface::latestRoundDataReturn { + roundId, + answer, + startedAt, + updatedAt, + answeredInRound, + } = self.contract.latestRoundData().call().await?; + + // Convert the price on contract to a string. + let float_price: f64 = answer.to_string().parse().unwrap(); + + // Convert the contract answer into a human-readable price + let human_price = float_price / (10f64.powi(self.decimals.into())); + + Ok(PriceData { + round_id: roundId, + answered_in_round: answeredInRound, + started_at: startedAt.to_string(), + updated_at: updatedAt.to_string(), + price: human_price, + }) + } +} + +#[cfg(test)] +mod tests { + + use alloy::providers::ProviderBuilder; + use reqwest::Url; + use std::str::FromStr; + + use crate::interface::ChainlinkContract; + + #[tokio::test] + async fn valid_answer() { + let provider = ProviderBuilder::new() + .on_http(Url::from_str("https://bsc-dataseed1.binance.org/").unwrap()); + + let chainlink_contract = + ChainlinkContract::new(provider, "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e") + .await + .unwrap(); + let price_data = chainlink_contract.get_price().await.unwrap(); + println!("Price check: {}", price_data.price); + println!("Round id: {}", price_data.round_id); + assert!(price_data.price.ge(&0f64)); + } +} diff --git a/src/lib.rs b/src/lib.rs index 36e90c3..d999c01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,166 @@ -pub mod chains; -pub mod core; \ No newline at end of file +mod fetcher; +mod interface; +use alloy::{ + providers::{ProviderBuilder, RootProvider}, + transports::http::Http, +}; +use log::LevelFilter; +use log4rs::{ + append::file::FileAppender, + config::{Appender, Root}, + encode::pattern::PatternEncoder, + Config, +}; +use reqwest::{Client, Url}; +use sled::Tree; +use std::str::FromStr; +use thiserror::Error; + +use self::{ + fetcher::fetch_prices, + interface::{PriceData, Serializable}, +}; + +#[derive(Clone)] +pub struct Configuration { + pub fetch_interval_seconds: u64, + pub contracts: Vec<(String, String)>, + pub provider: RootProvider>, +} + +/// ## Cryptoprices +/// +/// Cryptoprices is a lightweight Rust library that provides your Rust applications with a direct +/// link to the latest cryptocurrency prices. All data is retrieved from Chainlink decentralized +/// price feeds. Just copy the contract addresses for the symbol that you would like to track from: +/// https://data.chain.link/feeds. +/// +/// +/// Note: Rustlink is designed to be ran on the main thread, in an asynchronous tokio environment +#[derive(Clone)] +pub struct CryptoPrices { + configuration: Configuration, + tree: Tree, +} + +#[derive(Error, Debug)] +pub enum DatabaseError { + #[error("Could not find symbol")] + NotFound, + #[error("Could not deserialize binary data")] + Deserialize, + #[error("Database internal error: {0}")] + SledError(#[from] sled::Error), +} + +impl CryptoPrices { + /// Creates a new Rustlink instance. + /// + /// Expected parameters: + /// - `rpc_url`: The RPC url of your chosen EVM network where Chainlink offers decentralised data feeds. + /// Don't know where? Check https://data.chain.link/feeds. + /// - `fetch_interval_seconds`: How often to update prices in the database (to prevent RPC rate limitation) + /// - `sled_path`: The path for the database + /// - `contracts`: A tuple list containing a ticker name and its corresponding contract address on the + /// EVM chain. + /// + /// Example: + /// + /// ```rust + /// use cryptoprices::CryptoPrices; + /// let mut contracts:Vec<(String,String)>=Vec::new(); + /// contracts.push(("BTC".to_string(),"0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string())); + /// let crypto_prices=CryptoPrices::new("https://bsc-dataseed1.binance.org/",10,"./cryptoprices",contracts); + /// ``` + pub fn new( + rpc_url: &str, + fetch_interval_seconds: u64, + sled_path: &str, + contracts: Vec<(String, String)>, + ) -> CryptoPrices { + let db = sled::open(sled_path).unwrap(); + let provider = ProviderBuilder::new().on_http(Url::from_str(rpc_url).unwrap()); + + // Setup logging + let logfile = FileAppender::builder() + .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) + .build("./rustlink.log") + .unwrap(); + + let config = Config::builder() + .appender(Appender::builder().build("logfile", Box::new(logfile))) + .build(Root::builder().appender("logfile").build(LevelFilter::Info)) + .unwrap(); + + // Try to initialize and catch error silently if already initialized + // during tests this make this function throw error + if log4rs::init_config(config).is_err() { + println!("Logger already initialized."); + } + + CryptoPrices { + configuration: Configuration { + fetch_interval_seconds, + provider, + contracts, + }, + tree: db.open_tree("rustlink").unwrap(), + } + } + + /// Starts fetching prices in a new asynchronous task + /// from the chainlink contracts. + pub fn fetch(&self) { + tokio::spawn(fetch_prices(self.clone())); + } + + /// Helper function to retrieve data from the Sled db. + fn get_from_tree(db: &Tree, key: &str) -> Result, DatabaseError> { + Ok(db.get(key)?.ok_or(DatabaseError::NotFound)?.to_vec()) + } + + /// Public getter for reading the latest retrieved cryptocurrency price. + pub fn get_price(&self, ticker: &str) -> Result { + let binary_data = Self::get_from_tree(&self.tree, ticker)?; + PriceData::from_bin(binary_data).map_err(|error| { + log::error!("Deserialization: {}", error); + DatabaseError::Deserialize + }) + } +} + +#[cfg(test)] +mod tests { + + use crate::CryptoPrices; + use std::{fs, path::Path}; + fn remove_test_db(db_path: &str) { + if Path::new(db_path).exists() { + fs::remove_dir_all(db_path).expect("Failed to remove test database"); + } + } + #[tokio::test] + async fn ensure_price_is_received() { + let mut contracts: Vec<(String, String)> = Vec::new(); + contracts.push(( + "BTC".to_string(), + "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string(), + )); + let crypto_prices = CryptoPrices::new( + "https://bsc-dataseed1.binance.org/", + 1, + "./test-crypto-prices", + contracts, + ); + + crypto_prices.fetch(); + + // Within 10 seconds we can confidently check for price + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + let btc_price = crypto_prices.get_price("BTC").unwrap(); + println!("ETH Price: {}", btc_price.price); + println!("Updated at: {}", btc_price.updated_at); + remove_test_db("./test-crypto-prices"); + assert!(btc_price.price.ge(&0f64)); + } +} From 95914304ee6464300d7ce0b80ba85cdcf86f3fb5 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Mon, 13 May 2024 21:47:29 +0200 Subject: [PATCH 04/16] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aec9d69..d1a8ab1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# CryptoPrices +# `cryptoprices` A lightweight rust library for periodically retrieving cryptocurrency prices from the ChainLink decentralized price feed. From ffb94e6f39bd5257206d8a714e94ef9b675d9dbf Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Tue, 14 May 2024 01:53:28 +0200 Subject: [PATCH 05/16] Resolve PR suggestions, rename Todo: deprecate logging, DB and introduce channels Co-Authored-By: aspect <7544020+aspect@users.noreply.github.com> --- .gitignore | 2 +- Cargo.lock | 30 ++++----- Cargo.toml | 2 +- src/config.rs | 117 +++++++++++++++++++++++++++++++++++ src/error.rs | 11 ++++ src/fetcher/mod.rs | 43 ++++++------- src/interface/mod.rs | 48 +++++---------- src/lib.rs | 144 +++---------------------------------------- 8 files changed, 189 insertions(+), 208 deletions(-) create mode 100644 src/config.rs create mode 100644 src/error.rs diff --git a/.gitignore b/.gitignore index 5fc89cd..6953c19 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ +rustlink.log /target -rustlink.log \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 29fc84c..9cc5d6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -909,21 +909,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cryptoprices" -version = "0.1.0" -dependencies = [ - "alloy", - "bincode", - "log", - "log4rs", - "reqwest", - "serde", - "sled", - "thiserror", - "tokio", -] - [[package]] name = "dashmap" version = "5.5.3" @@ -2295,6 +2280,21 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustlink" +version = "0.1.0" +dependencies = [ + "alloy", + "bincode", + "log", + "log4rs", + "reqwest", + "serde", + "sled", + "thiserror", + "tokio", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" diff --git a/Cargo.toml b/Cargo.toml index 5787d83..6e25eba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "cryptoprices" +name = "rustlink" version = "0.1.0" edition = "2021" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..8acf2bf --- /dev/null +++ b/src/config.rs @@ -0,0 +1,117 @@ +use alloy::{ + providers::{ProviderBuilder, RootProvider}, + transports::http::Http, +}; +use log::LevelFilter; +use log4rs::{ + append::file::FileAppender, + config::{Appender, Root}, + encode::pattern::PatternEncoder, + Config, +}; +use reqwest::{Client, Url}; +use sled::Tree; +use std::{path::Path, str::FromStr}; +use crate::{ + error::Error, fetcher::fetch_rounds, interface::PriceData +}; + +#[derive(Clone)] +pub struct Configuration { + pub fetch_interval_seconds: u64, + pub contracts: Vec<(String, String)>, + pub provider: RootProvider>, +} + +/// ## Cryptoprices +/// +/// Cryptoprices is a lightweight Rust library that provides your Rust applications with a direct +/// link to the latest cryptocurrency prices. All data is retrieved from Chainlink decentralized +/// price feeds. Just copy the contract addresses for the symbol that you would like to track from: +/// https://data.chain.link/feeds. +/// +/// +/// Note: Rustlink is designed to be ran on the main thread, in an asynchronous tokio environment +#[derive(Clone)] +pub struct Rustlink { + pub configuration: Configuration, + pub tree: Tree, +} + + + +impl Rustlink { + /// Creates a new Rustlink instance. + /// + /// Expected parameters: + /// - `rpc_url`: The RPC url of your chosen EVM network where Chainlink offers decentralised data feeds. + /// Don't know where? Check https://data.chain.link/feeds. + /// - `fetch_interval_seconds`: How often to update data points in the database (to prevent RPC rate limitation) + /// - `sled_path`: The path for the database + /// - `contracts`: A tuple list containing a ticker name and its corresponding contract address on the + /// EVM chain. + /// + /// Example: + /// + /// ```rust + /// use rustlink::config::Rustlink; + /// let mut contracts:Vec<(String,String)>=Vec::new(); + /// contracts.push(("BTC".to_string(),"0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string())); + /// let crypto_prices=Rustlink::try_new("https://bsc-dataseed1.binance.org/",10,"./rustlink",contracts); + /// ``` + pub fn try_new

>( + rpc_url: &str, + fetch_interval_seconds: u64, + sled_path: P, + contracts: Vec<(String, String)>, + ) -> Result { + let db = sled::open(sled_path.as_ref())?; + let provider = ProviderBuilder::new().on_http(Url::from_str(rpc_url).unwrap()); + + // Setup logging + let logfile = FileAppender::builder() + .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) + .build("./rustlink.log") + .unwrap(); + + let config = Config::builder() + .appender(Appender::builder().build("logfile", Box::new(logfile))) + .build(Root::builder().appender("logfile").build(LevelFilter::Info)) + .unwrap(); + + // Try to initialize and catch error silently if already initialized + // during tests this make this function throw error + if log4rs::init_config(config).is_err() { + println!("Logger already initialized."); + } + + Ok(Rustlink { + configuration: Configuration { + fetch_interval_seconds, + provider, + contracts, + }, + tree: db.open_tree("rustlink").unwrap(), + }) + } + + /// Starts fetching data points in a new asynchronous task + /// from the chainlink contracts. + pub fn fetch(&self) { + tokio::spawn(fetch_rounds(self.clone())); + } + + /// Helper function to retrieve data from the Sled db. + fn get_from_tree(db: &Tree, key: &str) -> Result, Error> { + Ok(db.get(key)?.ok_or(Error::NotFound)?.to_vec()) + } + + /// Public getter for reading the latest retrieved cryptocurrency price. + pub fn get_answer(&self, ticker: &str) -> Result { + let binary_data = Self::get_from_tree(&self.tree, ticker)?; + bincode::deserialize::(&binary_data).map_err(|error| { + log::error!("Deserialization: {}", error); + Error::Deserialize + }) + } +} \ No newline at end of file diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..19f6d5e --- /dev/null +++ b/src/error.rs @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Could not find symbol")] + NotFound, + #[error("Could not deserialize binary data")] + Deserialize, + #[error("Database internal error: {0}")] + SledError(#[from] sled::Error), +} \ No newline at end of file diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs index b2a3fe2..b271140 100644 --- a/src/fetcher/mod.rs +++ b/src/fetcher/mod.rs @@ -1,40 +1,37 @@ -use super::{ - interface::{ChainlinkContract, PriceData, Serializable}, - Configuration, CryptoPrices, -}; +use crate::config::{Configuration, Rustlink}; + +use super::interface::{ChainlinkContract, PriceData}; /// Retrieves the price of an underlying asset from a particular contract -async fn fetch_price_for_contract( - rustlink_configuration: Configuration, +async fn fetch_round_data_for_contract( + rustlink_configuration: &Configuration, address: &str, ) -> Result { - let contract = ChainlinkContract::new(rustlink_configuration.provider, address).await?; - contract.get_price().await + let contract = ChainlinkContract::new(&rustlink_configuration.provider, address).await?; + contract.latest_round_data().await } /// A task that continously fetches cryptocurrency prices from Chainlink decentralised price data feed. -pub async fn fetch_prices(crypto_prices: CryptoPrices) { +pub async fn fetch_rounds(crypto_prices: Rustlink) { let contracts = &crypto_prices.configuration.contracts; loop { for contract_configuration in contracts { let symbol = &contract_configuration.0; let address = &contract_configuration.1; - match fetch_price_for_contract(crypto_prices.clone().configuration, address).await { - Ok(price_data) => { - match crypto_prices - .tree - .insert(symbol, price_data.to_bin().unwrap()) - { - Ok(_) => {} - Err(error) => { - log::error!("Could not update price in db: {}", error); - } - } - } - Err(error) => { - log::error!("Could not fetch price: {}", error); + match fetch_round_data_for_contract(&crypto_prices.configuration, address).await + .and_then(|price_data| Ok({ + let _ =crypto_prices.tree.insert( + symbol, + bincode::serialize::(&price_data).unwrap(), + ); + + })).or_else(|error| Err(error)) { + Ok(())=>{}, + Err(error)=>{ + log::error!("Failed updating price: {}",error); } } + tokio::time::sleep(std::time::Duration::from_secs( crypto_prices.configuration.fetch_interval_seconds, )) diff --git a/src/interface/mod.rs b/src/interface/mod.rs index a81a5d4..2763c7b 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -1,4 +1,4 @@ -use alloy::{contract::Error, providers::RootProvider, sol, transports::http::Http}; +use alloy::{contract::Error, primitives::Uint, providers::RootProvider, sol, transports::http::Http}; use reqwest::Client; use serde::{Deserialize, Serialize}; @@ -11,54 +11,37 @@ sol!( "src/abi/IAggregatorV3Interface.json" ); -pub trait Serializable { - fn to_bin(&self) -> Result, Box>; - fn from_bin(data: Vec) -> Result> - where - Self: Sized; -} - #[derive(Clone)] -pub struct ChainlinkContract { - pub contract: IAggregatorV3InterfaceInstance, RootProvider>>, +pub struct ChainlinkContract<'a> { + pub contract: IAggregatorV3InterfaceInstance, &'a RootProvider>>, pub decimals: u8, } /// The latest price received for this symbol. /// This data is directly retrieved from the underlying contract. -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize,Debug)] pub struct PriceData { /// Id of the submission by the aggregator pub round_id: u128, /// Answered in round pub answered_in_round: u128, /// Timestamp for when the aggregator started collecting data - pub started_at: String, + pub started_at: Uint<256,4>, /// Timestamp for when the aggregator posted the price update - pub updated_at: String, + pub updated_at: Uint<256,4>, /// Price of the asset pub price: f64, } -impl Serializable for PriceData { - /// Serializes invoice to bytes - fn to_bin(&self) -> Result, Box> { - bincode::serialize(&self) - } - /// Deserializes invoice from bytes - fn from_bin(data: Vec) -> Result> { - bincode::deserialize(&data) - } -} -impl ChainlinkContract { +impl<'a> ChainlinkContract<'a> { /// Creates a new instance of a chainlink price aggregator. This is just a wrapper /// function to simplify the interactions with the contract. pub async fn new( - provider: RootProvider>, + provider: &'a RootProvider>, contract_address: &str, - ) -> Result { + ) -> Result, Error> { let contract = IAggregatorV3Interface::new(contract_address.parse().unwrap(), provider); let IAggregatorV3Interface::decimalsReturn { _0: decimals } = @@ -68,7 +51,7 @@ impl ChainlinkContract { /// Retrieves the latest price of this underlying asset /// from the chainlink decentralized data feed - pub async fn get_price(&self) -> Result { + pub async fn latest_round_data(&self) -> Result { let IAggregatorV3Interface::latestRoundDataReturn { roundId, answer, @@ -86,8 +69,8 @@ impl ChainlinkContract { Ok(PriceData { round_id: roundId, answered_in_round: answeredInRound, - started_at: startedAt.to_string(), - updated_at: updatedAt.to_string(), + started_at: startedAt, + updated_at: updatedAt, price: human_price, }) } @@ -108,12 +91,11 @@ mod tests { .on_http(Url::from_str("https://bsc-dataseed1.binance.org/").unwrap()); let chainlink_contract = - ChainlinkContract::new(provider, "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e") + ChainlinkContract::new(&provider, "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e") .await .unwrap(); - let price_data = chainlink_contract.get_price().await.unwrap(); - println!("Price check: {}", price_data.price); - println!("Round id: {}", price_data.round_id); + let price_data = chainlink_contract.latest_round_data().await.unwrap(); + println!("Received data: {:#?}", price_data); assert!(price_data.price.ge(&0f64)); } } diff --git a/src/lib.rs b/src/lib.rs index d999c01..fbb8bc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,139 +1,14 @@ mod fetcher; mod interface; -use alloy::{ - providers::{ProviderBuilder, RootProvider}, - transports::http::Http, -}; -use log::LevelFilter; -use log4rs::{ - append::file::FileAppender, - config::{Appender, Root}, - encode::pattern::PatternEncoder, - Config, -}; -use reqwest::{Client, Url}; -use sled::Tree; -use std::str::FromStr; -use thiserror::Error; - -use self::{ - fetcher::fetch_prices, - interface::{PriceData, Serializable}, -}; - -#[derive(Clone)] -pub struct Configuration { - pub fetch_interval_seconds: u64, - pub contracts: Vec<(String, String)>, - pub provider: RootProvider>, -} - -/// ## Cryptoprices -/// -/// Cryptoprices is a lightweight Rust library that provides your Rust applications with a direct -/// link to the latest cryptocurrency prices. All data is retrieved from Chainlink decentralized -/// price feeds. Just copy the contract addresses for the symbol that you would like to track from: -/// https://data.chain.link/feeds. -/// -/// -/// Note: Rustlink is designed to be ran on the main thread, in an asynchronous tokio environment -#[derive(Clone)] -pub struct CryptoPrices { - configuration: Configuration, - tree: Tree, -} - -#[derive(Error, Debug)] -pub enum DatabaseError { - #[error("Could not find symbol")] - NotFound, - #[error("Could not deserialize binary data")] - Deserialize, - #[error("Database internal error: {0}")] - SledError(#[from] sled::Error), -} - -impl CryptoPrices { - /// Creates a new Rustlink instance. - /// - /// Expected parameters: - /// - `rpc_url`: The RPC url of your chosen EVM network where Chainlink offers decentralised data feeds. - /// Don't know where? Check https://data.chain.link/feeds. - /// - `fetch_interval_seconds`: How often to update prices in the database (to prevent RPC rate limitation) - /// - `sled_path`: The path for the database - /// - `contracts`: A tuple list containing a ticker name and its corresponding contract address on the - /// EVM chain. - /// - /// Example: - /// - /// ```rust - /// use cryptoprices::CryptoPrices; - /// let mut contracts:Vec<(String,String)>=Vec::new(); - /// contracts.push(("BTC".to_string(),"0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string())); - /// let crypto_prices=CryptoPrices::new("https://bsc-dataseed1.binance.org/",10,"./cryptoprices",contracts); - /// ``` - pub fn new( - rpc_url: &str, - fetch_interval_seconds: u64, - sled_path: &str, - contracts: Vec<(String, String)>, - ) -> CryptoPrices { - let db = sled::open(sled_path).unwrap(); - let provider = ProviderBuilder::new().on_http(Url::from_str(rpc_url).unwrap()); - - // Setup logging - let logfile = FileAppender::builder() - .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) - .build("./rustlink.log") - .unwrap(); - - let config = Config::builder() - .appender(Appender::builder().build("logfile", Box::new(logfile))) - .build(Root::builder().appender("logfile").build(LevelFilter::Info)) - .unwrap(); - - // Try to initialize and catch error silently if already initialized - // during tests this make this function throw error - if log4rs::init_config(config).is_err() { - println!("Logger already initialized."); - } - - CryptoPrices { - configuration: Configuration { - fetch_interval_seconds, - provider, - contracts, - }, - tree: db.open_tree("rustlink").unwrap(), - } - } - - /// Starts fetching prices in a new asynchronous task - /// from the chainlink contracts. - pub fn fetch(&self) { - tokio::spawn(fetch_prices(self.clone())); - } - - /// Helper function to retrieve data from the Sled db. - fn get_from_tree(db: &Tree, key: &str) -> Result, DatabaseError> { - Ok(db.get(key)?.ok_or(DatabaseError::NotFound)?.to_vec()) - } - - /// Public getter for reading the latest retrieved cryptocurrency price. - pub fn get_price(&self, ticker: &str) -> Result { - let binary_data = Self::get_from_tree(&self.tree, ticker)?; - PriceData::from_bin(binary_data).map_err(|error| { - log::error!("Deserialization: {}", error); - DatabaseError::Deserialize - }) - } -} +mod error; +pub mod config; #[cfg(test)] mod tests { - use crate::CryptoPrices; use std::{fs, path::Path}; + + use crate::config::Rustlink; fn remove_test_db(db_path: &str) { if Path::new(db_path).exists() { fs::remove_dir_all(db_path).expect("Failed to remove test database"); @@ -143,23 +18,22 @@ mod tests { async fn ensure_price_is_received() { let mut contracts: Vec<(String, String)> = Vec::new(); contracts.push(( - "BTC".to_string(), + "ETH".to_string(), "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string(), )); - let crypto_prices = CryptoPrices::new( + let crypto_prices = Rustlink::try_new( "https://bsc-dataseed1.binance.org/", 1, "./test-crypto-prices", contracts, - ); + ).unwrap(); crypto_prices.fetch(); // Within 10 seconds we can confidently check for price tokio::time::sleep(std::time::Duration::from_secs(10)).await; - let btc_price = crypto_prices.get_price("BTC").unwrap(); - println!("ETH Price: {}", btc_price.price); - println!("Updated at: {}", btc_price.updated_at); + let btc_price = crypto_prices.get_answer("ETH").unwrap(); + println!("Received data: {:#?}", btc_price); remove_test_db("./test-crypto-prices"); assert!(btc_price.price.ge(&0f64)); } From fa83944dfa590cd2d1710c4863cf6efc218d3a52 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Tue, 14 May 2024 01:53:32 +0200 Subject: [PATCH 06/16] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1a8ab1..7a84795 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# `cryptoprices` +# `rustlink` A lightweight rust library for periodically retrieving cryptocurrency prices from the ChainLink decentralized price feed. From d1caf9319a5c5163c0864e71d5c929a17db6bb77 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Wed, 15 May 2024 01:50:44 +0200 Subject: [PATCH 07/16] Deprecate databases introduce channels - add reflector enum that allows specification on how to receive round data Todo: deprecate global logging configuration in favor of custom logging functionality --- Cargo.lock | 483 ++++++++++++++++++++++++++++++++++--------- Cargo.toml | 2 +- src/config.rs | 67 +++--- src/error.rs | 4 +- src/fetcher/mod.rs | 57 ++--- src/interface/mod.rs | 58 +++--- src/lib.rs | 32 ++- 7 files changed, 510 insertions(+), 193 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9cc5d6b..47e9590 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -590,6 +590,143 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f2776ead772134d55b62dd45e59a79e21612d85d0af729b8b7d3967d601a62a" +dependencies = [ + "concurrent-queue", + "event-listener 5.3.0", + "event-listener-strategy 0.5.2", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.1.0", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.0", + "async-executor", + "async-io 2.3.2", + "async-lock 3.3.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.0", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -612,6 +749,12 @@ dependencies = [ "syn 2.0.61", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.80" @@ -623,6 +766,12 @@ dependencies = [ "syn 2.0.61", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "auto_impl" version = "1.2.0" @@ -730,6 +879,20 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" +dependencies = [ + "async-channel 2.3.0", + "async-lock 3.3.0", + "async-task", + "futures-io", + "futures-lite 2.3.0", + "piper", +] + [[package]] name = "blst" version = "0.3.11" @@ -807,6 +970,15 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-hex" version = "1.11.3" @@ -857,24 +1029,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" -dependencies = [ - "cfg-if", -] - -[[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.19" @@ -919,7 +1073,7 @@ dependencies = [ "hashbrown", "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] @@ -1053,6 +1207,63 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.0", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.1.0" @@ -1122,16 +1333,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "funty" version = "2.0.0" @@ -1186,6 +1387,34 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -1233,15 +1462,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1276,6 +1496,18 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -1453,7 +1685,7 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -1532,6 +1764,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1594,6 +1837,15 @@ dependencies = [ "sha3-asm", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1612,6 +1864,12 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -1635,6 +1893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", + "value-bag", ] [[package]] @@ -1659,7 +1918,7 @@ dependencies = [ "log", "log-mdc", "once_cell", - "parking_lot 0.12.2", + "parking_lot", "rand", "serde", "serde-value", @@ -1864,15 +2123,10 @@ dependencies = [ ] [[package]] -name = "parking_lot" -version = "0.11.2" +name = "parking" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -1881,21 +2135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -1906,7 +2146,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.1", + "redox_syscall", "smallvec", "windows-targets 0.52.5", ] @@ -1966,6 +2206,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464db0c665917b13ebb5d453ccdec4add5658ee1adc7affc7677615356a8afaf" +dependencies = [ + "atomic-waker", + "fastrand 2.1.0", + "futures-io", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -1982,6 +2233,37 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 0.38.34", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2121,15 +2403,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.1" @@ -2267,6 +2540,20 @@ dependencies = [ "semver 1.0.23", ] +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.34" @@ -2276,7 +2563,7 @@ dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] @@ -2285,12 +2572,12 @@ name = "rustlink" version = "0.1.0" dependencies = [ "alloy", + "async-std", "bincode", "log", "log4rs", "reqwest", "serde", - "sled", "thiserror", "tokio", ] @@ -2520,28 +2807,22 @@ dependencies = [ "autocfg", ] -[[package]] -name = "sled" -version = "0.34.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" -dependencies = [ - "crc32fast", - "crossbeam-epoch", - "crossbeam-utils", - "fs2", - "fxhash", - "libc", - "log", - "parking_lot 0.11.2", -] - [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.7" @@ -2648,8 +2929,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand", - "rustix", + "fastrand 2.1.0", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -2727,10 +3008,10 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot 0.12.2", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] @@ -2956,6 +3237,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2977,6 +3264,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index 6e25eba..621c523 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" [dependencies] log = "0.4.21" log4rs = "1.3.0" -sled = "0.34.7" tokio = {version="1.37.0",features=["full"]} alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0",features=["rpc-types-eth","eips","signers","signer-wallet","consensus","network","providers","transports","transport-http","contract"] } reqwest = "0.12.4" bincode = "1.3.3" serde = "1.0.201" thiserror = "1.0.60" +async-std = "1.12.0" diff --git a/src/config.rs b/src/config.rs index 8acf2bf..b64758e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,9 @@ +use crate::{error::Error, fetcher::fetch_rounds, interface::Round}; use alloy::{ providers::{ProviderBuilder, RootProvider}, transports::http::Http, }; +use async_std::channel::Sender; use log::LevelFilter; use log4rs::{ append::file::FileAppender, @@ -10,11 +12,7 @@ use log4rs::{ Config, }; use reqwest::{Client, Url}; -use sled::Tree; -use std::{path::Path, str::FromStr}; -use crate::{ - error::Error, fetcher::fetch_rounds, interface::PriceData -}; +use std::str::FromStr; #[derive(Clone)] pub struct Configuration { @@ -35,10 +33,30 @@ pub struct Configuration { #[derive(Clone)] pub struct Rustlink { pub configuration: Configuration, - pub tree: Tree, + pub reflector: Reflector, } - +/// Rustlink allows you as a developer to retrieve the sought Chainlink data in +/// different ways. +/// +/// In its current state you can pass a Sender from an unbound async-std channel +/// which you can create by doing: +/// ```rust +/// use async_std::channel::unbounded; +/// use rustlink::config::Reflector; +/// +/// let (sender, receiver) = unbounded(); +/// +/// let reflector=Reflector::Sender(sender); +/// ``` +/// +/// You may clone the receiver as many times as you want but do not use the sender +/// for anything other than passing it to the try_new() method. +#[derive(Clone)] +pub enum Reflector { + /// A sender from async-std + Sender(Sender), +} impl Rustlink { /// Creates a new Rustlink instance. @@ -47,7 +65,7 @@ impl Rustlink { /// - `rpc_url`: The RPC url of your chosen EVM network where Chainlink offers decentralised data feeds. /// Don't know where? Check https://data.chain.link/feeds. /// - `fetch_interval_seconds`: How often to update data points in the database (to prevent RPC rate limitation) - /// - `sled_path`: The path for the database + /// - `reflector`: How you choose to receive the answer from your provided contracts. /// - `contracts`: A tuple list containing a ticker name and its corresponding contract address on the /// EVM chain. /// @@ -55,17 +73,22 @@ impl Rustlink { /// /// ```rust /// use rustlink::config::Rustlink; + /// use async_std::channel::unbounded; + /// use rustlink::config::Reflector; /// let mut contracts:Vec<(String,String)>=Vec::new(); /// contracts.push(("BTC".to_string(),"0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string())); - /// let crypto_prices=Rustlink::try_new("https://bsc-dataseed1.binance.org/",10,"./rustlink",contracts); + /// + /// let (sender, receiver) = unbounded(); + /// + /// let reflector=Reflector::Sender(sender);/// + /// let crypto_prices=Rustlink::try_new("https://bsc-dataseed1.binance.org/",10,reflector,contracts); /// ``` - pub fn try_new

>( + pub fn try_new( rpc_url: &str, fetch_interval_seconds: u64, - sled_path: P, + reflector: Reflector, contracts: Vec<(String, String)>, - ) -> Result { - let db = sled::open(sled_path.as_ref())?; + ) -> Result { let provider = ProviderBuilder::new().on_http(Url::from_str(rpc_url).unwrap()); // Setup logging @@ -91,7 +114,7 @@ impl Rustlink { provider, contracts, }, - tree: db.open_tree("rustlink").unwrap(), + reflector, }) } @@ -100,18 +123,4 @@ impl Rustlink { pub fn fetch(&self) { tokio::spawn(fetch_rounds(self.clone())); } - - /// Helper function to retrieve data from the Sled db. - fn get_from_tree(db: &Tree, key: &str) -> Result, Error> { - Ok(db.get(key)?.ok_or(Error::NotFound)?.to_vec()) - } - - /// Public getter for reading the latest retrieved cryptocurrency price. - pub fn get_answer(&self, ticker: &str) -> Result { - let binary_data = Self::get_from_tree(&self.tree, ticker)?; - bincode::deserialize::(&binary_data).map_err(|error| { - log::error!("Deserialization: {}", error); - Error::Deserialize - }) - } -} \ No newline at end of file +} diff --git a/src/error.rs b/src/error.rs index 19f6d5e..ba0a1fd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,4 @@ pub enum Error { NotFound, #[error("Could not deserialize binary data")] Deserialize, - #[error("Database internal error: {0}")] - SledError(#[from] sled::Error), -} \ No newline at end of file +} diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs index b271140..a923716 100644 --- a/src/fetcher/mod.rs +++ b/src/fetcher/mod.rs @@ -1,47 +1,56 @@ +use super::interface::{ChainlinkContract, Round}; +use crate::config::Reflector::Sender; use crate::config::{Configuration, Rustlink}; -use super::interface::{ChainlinkContract, PriceData}; - /// Retrieves the price of an underlying asset from a particular contract async fn fetch_round_data_for_contract( rustlink_configuration: &Configuration, + identifier: &str, address: &str, -) -> Result { - let contract = ChainlinkContract::new(&rustlink_configuration.provider, address).await?; +) -> Result { + let contract = + ChainlinkContract::new(&rustlink_configuration.provider, identifier, address).await?; contract.latest_round_data().await } -/// A task that continously fetches cryptocurrency prices from Chainlink decentralised price data feed. -pub async fn fetch_rounds(crypto_prices: Rustlink) { - let contracts = &crypto_prices.configuration.contracts; +// The function signature looks good, but ensure all types (Rustlink, Round, etc.) are properly defined. +pub async fn fetch_rounds(rustlink: Rustlink) { + let contracts = &rustlink.configuration.contracts; + + // This loop runs indefinitely, fetching price data. loop { for contract_configuration in contracts { - let symbol = &contract_configuration.0; + let identifier = &contract_configuration.0; // This variable wasn't used in your original code. let address = &contract_configuration.1; - match fetch_round_data_for_contract(&crypto_prices.configuration, address).await - .and_then(|price_data| Ok({ - let _ =crypto_prices.tree.insert( - symbol, - bincode::serialize::(&price_data).unwrap(), - ); - })).or_else(|error| Err(error)) { - Ok(())=>{}, - Err(error)=>{ - log::error!("Failed updating price: {}",error); + // Fetch price data and attempt to send it via the channel. + match fetch_round_data_for_contract(&rustlink.configuration, identifier, address).await + { + Ok(price_data) => { + match rustlink.reflector { + Sender(ref sender) => { + // Attempt to send the PriceData through the channel. + if let Err(error) = sender.send(price_data).await { + log::error!("Failed sending data: {}", error); + } + } + } + } + Err(error) => { + log::error!("Failed updating price: {}", error); } } + // Wait for the specified interval before fetching the next price. tokio::time::sleep(std::time::Duration::from_secs( - crypto_prices.configuration.fetch_interval_seconds, + rustlink.configuration.fetch_interval_seconds, )) .await; } - // Give back control to tokio runtime. - tokio::time::sleep(std::time::Duration::from_secs( - crypto_prices.configuration.fetch_interval_seconds, - )) - .await; + // Depending on your intention, you might not need this additional sleep here because + // the loop itself already waits after each contract is fetched, which might be enough. + // If you wish all contracts to be fetched at once and then wait, keep this. + // Otherwise, it might cause longer than expected delays between fetches. } } diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 2763c7b..bdd15dd 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -1,4 +1,6 @@ -use alloy::{contract::Error, primitives::Uint, providers::RootProvider, sol, transports::http::Http}; +use alloy::{ + contract::Error, primitives::Uint, providers::RootProvider, sol, transports::http::Http, +}; use reqwest::Client; use serde::{Deserialize, Serialize}; @@ -14,44 +16,50 @@ sol!( #[derive(Clone)] pub struct ChainlinkContract<'a> { pub contract: IAggregatorV3InterfaceInstance, &'a RootProvider>>, + pub identifier: &'a str, pub decimals: u8, } /// The latest price received for this symbol. /// This data is directly retrieved from the underlying contract. -#[derive(Deserialize, Serialize,Debug)] -pub struct PriceData { +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct Round { + // Identifier of the underlying asset + pub identifier: String, /// Id of the submission by the aggregator pub round_id: u128, /// Answered in round pub answered_in_round: u128, /// Timestamp for when the aggregator started collecting data - pub started_at: Uint<256,4>, + pub started_at: Uint<256, 4>, /// Timestamp for when the aggregator posted the price update - pub updated_at: Uint<256,4>, - /// Price of the asset - pub price: f64, + pub updated_at: Uint<256, 4>, + /// Answer of this round + pub answer: f64, } - - impl<'a> ChainlinkContract<'a> { /// Creates a new instance of a chainlink price aggregator. This is just a wrapper /// function to simplify the interactions with the contract. pub async fn new( provider: &'a RootProvider>, + identifier: &'a str, contract_address: &str, - ) -> Result, Error> { + ) -> Result, Error> { let contract = IAggregatorV3Interface::new(contract_address.parse().unwrap(), provider); let IAggregatorV3Interface::decimalsReturn { _0: decimals } = contract.decimals().call().await?; - Ok(ChainlinkContract { contract, decimals }) + Ok(ChainlinkContract { + contract, + decimals, + identifier, + }) } /// Retrieves the latest price of this underlying asset /// from the chainlink decentralized data feed - pub async fn latest_round_data(&self) -> Result { + pub async fn latest_round_data(&self) -> Result { let IAggregatorV3Interface::latestRoundDataReturn { roundId, answer, @@ -60,18 +68,19 @@ impl<'a> ChainlinkContract<'a> { answeredInRound, } = self.contract.latestRoundData().call().await?; - // Convert the price on contract to a string. - let float_price: f64 = answer.to_string().parse().unwrap(); + // Convert the answer on contract to a string. + let float_answer: f64 = answer.to_string().parse().unwrap(); - // Convert the contract answer into a human-readable price - let human_price = float_price / (10f64.powi(self.decimals.into())); + // Convert the contract answer into a human-readable answer + let human_answer = float_answer / (10f64.powi(self.decimals.into())); - Ok(PriceData { + Ok(Round { + identifier: self.identifier.to_string(), round_id: roundId, answered_in_round: answeredInRound, started_at: startedAt, updated_at: updatedAt, - price: human_price, + answer: human_answer, }) } } @@ -90,12 +99,15 @@ mod tests { let provider = ProviderBuilder::new() .on_http(Url::from_str("https://bsc-dataseed1.binance.org/").unwrap()); - let chainlink_contract = - ChainlinkContract::new(&provider, "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e") - .await - .unwrap(); + let chainlink_contract = ChainlinkContract::new( + &provider, + "ETH", + "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e", + ) + .await + .unwrap(); let price_data = chainlink_contract.latest_round_data().await.unwrap(); println!("Received data: {:#?}", price_data); - assert!(price_data.price.ge(&0f64)); + assert!(price_data.answer.ge(&0f64)); } } diff --git a/src/lib.rs b/src/lib.rs index fbb8bc2..ce4d491 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,19 +1,15 @@ +pub mod config; +mod error; mod fetcher; mod interface; -mod error; -pub mod config; #[cfg(test)] mod tests { - use std::{fs, path::Path}; + use async_std::channel::unbounded; + + use crate::config::{Reflector, Rustlink}; - use crate::config::Rustlink; - fn remove_test_db(db_path: &str) { - if Path::new(db_path).exists() { - fs::remove_dir_all(db_path).expect("Failed to remove test database"); - } - } #[tokio::test] async fn ensure_price_is_received() { let mut contracts: Vec<(String, String)> = Vec::new(); @@ -21,20 +17,20 @@ mod tests { "ETH".to_string(), "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string(), )); + + let (sender, receiver) = unbounded(); + let crypto_prices = Rustlink::try_new( "https://bsc-dataseed1.binance.org/", 1, - "./test-crypto-prices", + Reflector::Sender(sender), contracts, - ).unwrap(); + ) + .unwrap(); crypto_prices.fetch(); - - // Within 10 seconds we can confidently check for price - tokio::time::sleep(std::time::Duration::from_secs(10)).await; - let btc_price = crypto_prices.get_answer("ETH").unwrap(); - println!("Received data: {:#?}", btc_price); - remove_test_db("./test-crypto-prices"); - assert!(btc_price.price.ge(&0f64)); + let round_data = receiver.recv().await.unwrap(); + println!("Received data: {:#?}", round_data); + assert!(round_data.answer.ge(&0f64)); } } From dae3feef19b2d4eb24cb6d04074711c5b0e5005c Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Wed, 15 May 2024 17:44:38 +0200 Subject: [PATCH 08/16] WASM, shutdown signals, logging, js example - Added WASM compatibility and WASM build scripts - Added graceful shutdown - Deprecated global logging configuration --- Cargo.lock | 1235 +++++++++++++++++++++++++++++++++++++++----- Cargo.toml | 26 +- js/index.html | 43 ++ node-build.sh | 1 + src/config.rs | 144 ++++-- src/fetcher/mod.rs | 64 ++- src/lib.rs | 4 +- web-build.sh | 1 + 8 files changed, 1333 insertions(+), 185 deletions(-) create mode 100644 js/index.html create mode 100755 node-build.sh create mode 100755 web-build.sh diff --git a/Cargo.lock b/Cargo.lock index 47e9590..acfc43f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,18 +17,39 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "getrandom", "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 = "allocator-api2" version = "0.2.18" @@ -191,7 +212,7 @@ checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" dependencies = [ "alloy-rlp", "bytes", - "cfg-if", + "cfg-if 1.0.0", "const-hex", "derive_more", "hex-literal", @@ -407,7 +428,7 @@ version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy#6c58a0a2f1b2325aeba6a359e5ea5f4faa08bda0" dependencies = [ "alloy-json-rpc", - "base64", + "base64 0.22.1", "futures-util", "futures-utils-wasm", "serde", @@ -590,6 +611,16 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -650,7 +681,7 @@ checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock 2.8.0", "autocfg", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-lite 1.13.0", "log", @@ -669,7 +700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock 3.3.0", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite 2.3.0", @@ -707,6 +738,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ + "async-attributes", "async-channel 1.9.0", "async-global-executor", "async-io 1.13.0", @@ -772,6 +804,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "auto_impl" version = "1.2.0" @@ -797,7 +840,7 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -810,6 +853,12 @@ 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 = "base64" version = "0.22.1" @@ -905,6 +954,60 @@ dependencies = [ "zeroize", ] +[[package]] +name = "borsh" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +dependencies = [ + "borsh-derive", + "hashbrown 0.11.2", +] + +[[package]] +name = "borsh-derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -946,18 +1049,68 @@ dependencies = [ "serde", ] +[[package]] +name = "camino" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cc" version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrome-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c631c2cf4b95746cf065f732219ec0f2eb1497cd4c7fe07cb336ddf0d7c503" +dependencies = [ + "js-sys", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", +] + [[package]] name = "chrono" version = "0.4.38" @@ -966,7 +1119,9 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", + "wasm-bindgen", "windows-targets 0.52.5", ] @@ -979,13 +1134,26 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + [[package]] name = "const-hex" version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "hex", "proptest", @@ -1004,6 +1172,15 @@ 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" @@ -1035,6 +1212,31 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags 2.5.0", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -1069,13 +1271,19 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if", - "hashbrown", + "cfg-if 1.0.0", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", ] +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + [[package]] name = "der" version = "0.7.9" @@ -1086,6 +1294,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1103,19 +1320,13 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version 0.4.0", "syn 1.0.109", ] -[[package]] -name = "destructure_traitobject" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c877555693c14d2f84191cfd3ad8582790fc52b5e2274b40b59cf5f5cea25c7" - [[package]] name = "digest" version = "0.9.0" @@ -1137,6 +1348,39 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dunce" version = "1.0.4" @@ -1182,13 +1426,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1255,6 +1505,15 @@ dependencies = [ "pin-project-lite", ] +[[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 = "1.9.0" @@ -1291,6 +1550,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -1479,9 +1750,11 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1538,13 +1811,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.8", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.11", "allocator-api2", ] @@ -1560,6 +1842,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.9" @@ -1581,6 +1872,16 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hexplay" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da1f4f846e8dcc1b5225caf702924816cabd855e4b46115c334ba09d5254a21" +dependencies = [ + "atty", + "termcolor", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1590,6 +1891,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "1.1.0" @@ -1630,12 +1940,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "1.3.1" @@ -1752,7 +2056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1761,7 +2065,10 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -1770,7 +2077,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -1820,7 +2127,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "ecdsa", "elliptic-curve", "once_cell", @@ -1864,6 +2171,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -1892,51 +2209,25 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ - "serde", "value-bag", ] [[package]] -name = "log-mdc" -version = "0.1.0" +name = "lru" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.5", +] [[package]] -name = "log4rs" -version = "1.3.0" +name = "manual_future" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0816135ae15bd0391cf284eab37e6e3ee0a6ee63d2ceeb659862bd8d0a984ca6" +checksum = "943968aefb9b0fdf36cccc03f6cd9d6698b23574ab49eccc185ae6c5cb6ad43e" dependencies = [ - "anyhow", - "arc-swap", - "chrono", - "derivative", - "fnv", - "humantime", - "libc", - "log", - "log-mdc", - "once_cell", - "parking_lot", - "rand", - "serde", - "serde-value", - "serde_json", - "serde_yaml", - "thiserror", - "thread-id", - "typemap-ors", - "winapi", -] - -[[package]] -name = "lru" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" -dependencies = [ - "hashbrown", + "futures", ] [[package]] @@ -1967,6 +2258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -1989,6 +2281,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "node-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d75eee6e8b159228449706773f9f2af60720250308124e9c3d38bd8070844a" +dependencies = [ + "cfg-if 0.1.10", + "js-sys", + "serde", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "num-bigint" version = "0.4.5" @@ -1999,6 +2304,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.46" @@ -2024,10 +2335,38 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "numtoa" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" + +[[package]] +name = "nw-sys" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ebcbbf8ce75f465eea419ed8396efaf9ad9da87ad83fe9fce9c8789de00ca79" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "thiserror", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "object" version = "0.32.2" @@ -2050,7 +2389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", @@ -2088,12 +2427,18 @@ dependencies = [ ] [[package]] -name = "ordered-float" -version = "2.10.1" +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "pad" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "num-traits", + "unicode-width", ] [[package]] @@ -2116,7 +2461,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2144,13 +2489,33 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", "windows-targets 0.52.5", ] +[[package]] +name = "parse-variants" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f048110646aae15ec0e4299c37a012739d28d92c82b7ad945c0578c188cbe3" +dependencies = [ + "parse-variants-derive", +] + +[[package]] +name = "parse-variants-derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70df726c43c645ef1dde24c7ae14692036ebe5457c92c5f0ec4cfceb99634ff6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + [[package]] name = "paste" version = "1.0.15" @@ -2241,7 +2606,7 @@ checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "libc", "log", @@ -2255,15 +2620,21 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.3.9", "pin-project-lite", "rustix 0.38.34", "tracing", "windows-sys 0.52.0", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2281,6 +2652,15 @@ dependencies = [ "uint", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -2403,6 +2783,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.5.1" @@ -2412,6 +2801,40 @@ dependencies = [ "bitflags 2.5.0", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.8.3" @@ -2424,7 +2847,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -2470,6 +2893,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "ritehash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80eb5f11ebcdd09266eb7897503d7451c2fceea3881538c63dd2651e2c5ebe0c" + [[package]] name = "rlp" version = "0.5.2" @@ -2574,12 +3003,17 @@ dependencies = [ "alloy", "async-std", "bincode", + "futures", + "js-sys", "log", - "log4rs", "reqwest", "serde", + "serde-wasm-bindgen", "thiserror", "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "workflow-rs", ] [[package]] @@ -2588,7 +3022,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] @@ -2598,6 +3032,12 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + [[package]] name = "rusty-fork" version = "0.3.0" @@ -2682,6 +3122,9 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "semver-parser" @@ -2702,13 +3145,14 @@ dependencies = [ ] [[package]] -name = "serde-value" -version = "0.7.0" +name = "serde-wasm-bindgen" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" dependencies = [ - "ordered-float", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -2746,16 +3190,14 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" +name = "sha1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", ] [[package]] @@ -2764,7 +3206,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.10.7", ] @@ -2776,7 +3218,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio", + "signal-hook", ] [[package]] @@ -2813,6 +3276,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + [[package]] name = "socket2" version = "0.4.10" @@ -2928,12 +3397,32 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand 2.1.0", "rustix 0.38.34", "windows-sys 0.52.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.60" @@ -2955,22 +3444,45 @@ dependencies = [ ] [[package]] -name = "thread-id" -version = "4.2.1" +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ec81c46e9eb50deaa257be2f148adf052d1fb7701cfd55ccfab2525280b70b" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", + "itoa", "libc", - "winapi", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", ] [[package]] -name = "threadpool" -version = "1.8.1" +name = "time-core" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ - "num_cpus", + "num-conv", + "time-core", ] [[package]] @@ -3008,9 +3520,7 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", @@ -3049,6 +3559,20 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "tokio-tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +dependencies = [ + "futures-util", + "log", + "native-tls", + "tokio", + "tokio-native-tls", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.11" @@ -3062,6 +3586,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml_datetime" version = "0.6.5" @@ -3139,6 +3672,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "triggered" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce148eae0d1a376c1b94ae651fc3261d9cb8294788b962b7382066376503a2d1" + [[package]] name = "try-lock" version = "0.2.5" @@ -3146,12 +3685,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "typemap-ors" -version = "1.0.0" +name = "tungstenite" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68c24b707f02dd18f1e4ccceb9d49f2058c2fb86384ef9972592904d7a28867" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ - "unsafe-any-ors", + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "native-tls", + "rand", + "sha1", + "thiserror", + "url", + "utf-8", ] [[package]] @@ -3196,6 +3746,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.23" @@ -3206,19 +3762,16 @@ dependencies = [ ] [[package]] -name = "unsafe-any-ors" -version = "1.0.0" +name = "unicode-segmentation" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a303d30665362d9680d7d91d78b23f5f899504d4f08b3c4cf08d055d87c0ad" -dependencies = [ - "destructure_traitobject", -] +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] -name = "unsafe-libyaml" -version = "0.2.11" +name = "unicode-width" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "url" @@ -3231,6 +3784,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "valuable" version = "0.1.0" @@ -3249,6 +3808,21 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vergen" +version = "8.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +dependencies = [ + "anyhow", + "cargo_metadata", + "cfg-if 1.0.0", + "regex", + "rustc_version 0.4.0", + "rustversion", + "time", +] + [[package]] name = "version_check" version = "0.9.4" @@ -3291,7 +3865,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -3316,7 +3890,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -3377,6 +3951,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3555,10 +4138,420 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] +[[package]] +name = "workflow-chrome" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109b6289f65b3e1cdfa6f2d9e8eb454453d5763c5061350e2300473c48d91b99" +dependencies = [ + "cfg-if 1.0.0", + "chrome-sys", + "js-sys", + "thiserror", + "wasm-bindgen", + "workflow-core", + "workflow-log", +] + +[[package]] +name = "workflow-core" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcea01cb6122ac3f20dc14f8e4104e2c0cd9c718c17ddb3fc115f9b2ed99f9ae" +dependencies = [ + "async-channel 2.3.0", + "async-std", + "borsh", + "bs58", + "cfg-if 1.0.0", + "chrono", + "dirs", + "faster-hex", + "futures", + "getrandom", + "instant", + "js-sys", + "rand", + "serde", + "serde-wasm-bindgen", + "thiserror", + "tokio", + "triggered", + "vergen", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "workflow-core-macros", +] + +[[package]] +name = "workflow-core-macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe24820a62e2b544c75c000cff72781383495a0e05157ec3e29b2abafe1ca2cb" +dependencies = [ + "convert_case 0.6.0", + "parse-variants", + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "sha2", + "syn 1.0.109", + "workflow-macro-tools", +] + +[[package]] +name = "workflow-dom" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91264d4e789f23c6730c2f3adede04a24b6a9eb9797f9d4ab23de370ba04c27f" +dependencies = [ + "futures", + "js-sys", + "regex", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "workflow-core", + "workflow-log", + "workflow-wasm", +] + +[[package]] +name = "workflow-html" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca44f996326b5f62655ee78aef430e0daa0c4f6f025e75b9d470fc58c2d8488" +dependencies = [ + "lazy_static", + "regex", + "wasm-bindgen", + "web-sys", + "workflow-html-macros", +] + +[[package]] +name = "workflow-html-macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f000da252afe95444bb5d91c3e6df6fd0f2b12f816ecea74d1124c08597d53c" +dependencies = [ + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "rand", + "syn 1.0.109", +] + +[[package]] +name = "workflow-i18n" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb62e7cbafa88f8e75845a707a28acc48939aecdefd9d188fa11d8b2fe47a94" +dependencies = [ + "arc-swap", + "cfg-if 1.0.0", + "itertools 0.12.1", + "ritehash", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "workflow-log" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077a8f720aa45c8cd867de1ccc73e068c4084d9fea46d11be7697a108e6a00ba" +dependencies = [ + "cfg-if 1.0.0", + "console", + "downcast", + "hexplay", + "lazy_static", + "log", + "termcolor", + "wasm-bindgen", +] + +[[package]] +name = "workflow-macro-tools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a8af8b8951fa0cf94df4057b8cf583e067a525d3d997370db7797f33ba201f" +dependencies = [ + "convert_case 0.6.0", + "parse-variants", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "workflow-node" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7748eb6c76779993ed7f4457356d6b57f48f97f9e264c64c3405098330bcb8c7" +dependencies = [ + "borsh", + "futures", + "js-sys", + "lazy_static", + "node-sys", + "serde", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "workflow-core", + "workflow-log", + "workflow-task", + "workflow-wasm", +] + +[[package]] +name = "workflow-panic-hook" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c1ed51290daf255e5fd83dfe6bd754b108e371b971afbb5c5fd1ea8fe148af" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "workflow-rpc" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14784fbad27d0403fc752d835c4c4683cfc6af970a484ea83f40ce7ad6dc7745" +dependencies = [ + "ahash 0.8.11", + "async-std", + "async-trait", + "borsh", + "downcast-rs", + "futures", + "futures-util", + "getrandom", + "manual_future", + "rand", + "serde", + "serde_json", + "thiserror", + "tokio", + "tungstenite", + "wasm-bindgen", + "workflow-core", + "workflow-log", + "workflow-rpc-macros", + "workflow-task", + "workflow-wasm", + "workflow-websocket", +] + +[[package]] +name = "workflow-rpc-macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c372e99d1336a137b907274a3c50fc195e30141c87fc6da4dba54e7d4b09b8ec" +dependencies = [ + "parse-variants", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "workflow-rs" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d08e4100628ddf1d7a2e3b2e88a55cfe1dab569b743e0bf9eb2fb2ed5e0f914" +dependencies = [ + "workflow-core", + "workflow-dom", + "workflow-html", + "workflow-i18n", + "workflow-log", + "workflow-rpc", + "workflow-store", + "workflow-terminal", + "workflow-wasm", + "workflow-websocket", +] + +[[package]] +name = "workflow-store" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "762861614298160b9205302bec4f2b7eb45853413d10a90ad8edca44bafc324b" +dependencies = [ + "async-std", + "base64 0.21.7", + "cfg-if 1.0.0", + "chrome-sys", + "faster-hex", + "filetime", + "home", + "js-sys", + "lazy_static", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "workflow-chrome", + "workflow-core", + "workflow-log", + "workflow-node", + "workflow-wasm", +] + +[[package]] +name = "workflow-task" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4023e2598734e04aa4e968a4dd1cd2b5d0c344edc38b40970926d5742f5afa0" +dependencies = [ + "futures", + "thiserror", + "workflow-core", + "workflow-task-macros", +] + +[[package]] +name = "workflow-task-macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057801365ce04c520a2a694bc5bfdf1784f1a33fff97af4cd735f94eb12947b1" +dependencies = [ + "convert_case 0.6.0", + "parse-variants", + "proc-macro-error", + "proc-macro2", + "quote", + "sha2", + "syn 1.0.109", + "workflow-macro-tools", +] + +[[package]] +name = "workflow-terminal" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "895c236dd5cf493e01fc31733c4687b3e67032f610d594ce3b8e5cafd14eaf33" +dependencies = [ + "async-std", + "async-trait", + "cfg-if 1.0.0", + "crossterm", + "downcast", + "futures", + "js-sys", + "numtoa", + "nw-sys", + "pad", + "regex", + "textwrap", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "workflow-core", + "workflow-dom", + "workflow-log", + "workflow-terminal-macros", + "workflow-wasm", +] + +[[package]] +name = "workflow-terminal-macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1fe67beb12d31f2e69715898aa32abd2349ffc8fe0555617f0d77500cebc56" +dependencies = [ + "convert_case 0.6.0", + "parse-variants", + "proc-macro-error", + "proc-macro2", + "quote", + "sha2", + "syn 1.0.109", + "workflow-macro-tools", +] + +[[package]] +name = "workflow-wasm" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ffbd1de665304ba6040a1ab4e0867fd9174446491d257bc6a1474ae25d4a6c" +dependencies = [ + "cfg-if 1.0.0", + "faster-hex", + "futures", + "js-sys", + "serde", + "serde-wasm-bindgen", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "workflow-core", + "workflow-log", + "workflow-panic-hook", + "workflow-wasm-macros", +] + +[[package]] +name = "workflow-wasm-macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082644f52215ecc86b4b8a20a763e482adee52c338208ade268f47fe25eb07ca" +dependencies = [ + "js-sys", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen", +] + +[[package]] +name = "workflow-websocket" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6967baf2bd85deb2a014a32d34c1664ded9333e10d11d43ffc179fa09cc55db8" +dependencies = [ + "ahash 0.8.11", + "async-channel 2.3.0", + "async-std", + "async-trait", + "cfg-if 1.0.0", + "downcast-rs", + "futures", + "futures-util", + "js-sys", + "thiserror", + "tokio", + "tokio-tungstenite", + "triggered", + "tungstenite", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "workflow-core", + "workflow-log", + "workflow-task", + "workflow-wasm", +] + [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 621c523..8bbad8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,11 +5,31 @@ edition = "2021" [dependencies] log = "0.4.21" -log4rs = "1.3.0" -tokio = {version="1.37.0",features=["full"]} -alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0",features=["rpc-types-eth","eips","signers","signer-wallet","consensus","network","providers","transports","transport-http","contract"] } +alloy = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0", features = ["rpc-types-eth","eips","signers","signer-wallet","consensus","network","providers","transports","transport-http","contract"] } reqwest = "0.12.4" bincode = "1.3.3" serde = "1.0.201" thiserror = "1.0.60" +workflow-rs = { version = "0.12.1", features = ["full"] } + +# Async-std included for all builds async-std = "1.12.0" +wasm-bindgen = "0.2.92" +js-sys = "0.3.69" +wasm-bindgen-futures = "0.4.42" +serde-wasm-bindgen = "0.6.5" +futures = "0.3.30" + +# Dependencies for non-WASM targets +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +tokio = "1.37.0" + +# Optional dependencies or features specific to WASM can be added here +[target.'cfg(target_arch = "wasm32")'.dependencies] +# Add wasm-specific dependencies if any (e.g. wasm-bindgen, web-sys, etc.) + +[lints.clippy] +empty_docs = "allow" + +[lib] +crate-type = ["cdylib", "rlib"] diff --git a/js/index.html b/js/index.html new file mode 100644 index 0000000..bf5cf1b --- /dev/null +++ b/js/index.html @@ -0,0 +1,43 @@ + + + + + Rust WASM Example + + + +

Check the console for output

+ + \ No newline at end of file diff --git a/node-build.sh b/node-build.sh new file mode 100755 index 0000000..ad7d6ed --- /dev/null +++ b/node-build.sh @@ -0,0 +1 @@ +wasm-pack build --target nodejs --out-name rustlink --out-dir js/node \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index b64758e..4592ccf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,16 +3,14 @@ use alloy::{ providers::{ProviderBuilder, RootProvider}, transports::http::Http, }; -use async_std::channel::Sender; -use log::LevelFilter; -use log4rs::{ - append::file::FileAppender, - config::{Appender, Root}, - encode::pattern::PatternEncoder, - Config, -}; +use async_std::channel::{unbounded, Receiver, RecvError, Sender}; +use js_sys::Function; use reqwest::{Client, Url}; +use serde_wasm_bindgen::{from_value, to_value}; use std::str::FromStr; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; +use wasm_bindgen_futures::spawn_local; +use workflow_rs::core::cfg_if; #[derive(Clone)] pub struct Configuration { @@ -21,9 +19,9 @@ pub struct Configuration { pub provider: RootProvider>, } -/// ## Cryptoprices +/// ## Rustlink /// -/// Cryptoprices is a lightweight Rust library that provides your Rust applications with a direct +/// Rustlink is a lightweight Rust library that provides your Rust applications with a direct /// link to the latest cryptocurrency prices. All data is retrieved from Chainlink decentralized /// price feeds. Just copy the contract addresses for the symbol that you would like to track from: /// https://data.chain.link/feeds. @@ -34,6 +32,10 @@ pub struct Configuration { pub struct Rustlink { pub configuration: Configuration, pub reflector: Reflector, + pub termination_send: Sender<()>, + pub termination_recv: Receiver<()>, + pub shutdown_send: Sender<()>, + pub shutdown_recv: Receiver<()>, } /// Rustlink allows you as a developer to retrieve the sought Chainlink data in @@ -90,24 +92,8 @@ impl Rustlink { contracts: Vec<(String, String)>, ) -> Result { let provider = ProviderBuilder::new().on_http(Url::from_str(rpc_url).unwrap()); - - // Setup logging - let logfile = FileAppender::builder() - .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) - .build("./rustlink.log") - .unwrap(); - - let config = Config::builder() - .appender(Appender::builder().build("logfile", Box::new(logfile))) - .build(Root::builder().appender("logfile").build(LevelFilter::Info)) - .unwrap(); - - // Try to initialize and catch error silently if already initialized - // during tests this make this function throw error - if log4rs::init_config(config).is_err() { - println!("Logger already initialized."); - } - + let (termination_send, termination_recv) = unbounded::<()>(); + let (shutdown_send, shutdown_recv) = unbounded::<()>(); Ok(Rustlink { configuration: Configuration { fetch_interval_seconds, @@ -115,12 +101,106 @@ impl Rustlink { contracts, }, reflector, + termination_send, + termination_recv, + shutdown_send, + shutdown_recv, }) } - /// Starts fetching data points in a new asynchronous task - /// from the chainlink contracts. - pub fn fetch(&self) { - tokio::spawn(fetch_rounds(self.clone())); + pub fn start(&self) { + #[cfg(not(target_arch = "wasm32"))] + tokio::task::spawn(fetch_rounds(self.clone())); + + #[cfg(target_arch = "wasm32")] + async_std::task::block_on(fetch_rounds(self.clone())); + } + + pub async fn stop(&self) -> Result<(), RecvError> { + self.termination_send.send(()).await.unwrap(); + self.shutdown_recv.recv().await + } +} +#[wasm_bindgen] +pub struct RustlinkJS { + rustlink: Rustlink, + callback: Function, + receiver: Receiver, +} + +cfg_if! { + if #[cfg(target_arch = "wasm32")] { + #[wasm_bindgen(typescript_custom_section)] + const TS_CONTRACTS: &'static str = r#" + /** + * A contract tuple containing an identifier and a contract address. + * + * **Order matters.** + * Example + * ```typescript + * let contracts=[["Ethereum","0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e"]] + * ``` + */ + export type Contract = [string,string] + "#; + + } +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = js_sys::Function, typescript_type = "Contract[]")] + pub type Contracts; +} + +#[wasm_bindgen] +impl RustlinkJS { + /// Creates a new RustlinkJS instance + #[wasm_bindgen(constructor)] + pub fn new( + rpc_url: &str, + fetch_interval_seconds: u64, + contracts: Contracts, + callback: Function, + ) -> Self { + // Cast `JsValue` to `Function` + + let contracts: Vec<(String, String)> = from_value(contracts.into()).unwrap(); + + let (sender, receiver) = async_std::channel::unbounded(); + let reflector = Reflector::Sender(sender); + let rustlink = Rustlink::try_new(rpc_url, fetch_interval_seconds, reflector, contracts) + .map_err(|e| JsValue::from_str(&format!("{}", e))) + .unwrap(); + + RustlinkJS { + rustlink, + callback, + receiver, + } + } + #[wasm_bindgen] + pub fn start(&self) { + self.rustlink.start(); + let receiver = self.receiver.clone(); + let callback = self.callback.clone(); + spawn_local(async move { + while let Ok(round) = receiver.recv().await { + // Prepare arguments to pass to JS function + let this = JsValue::NULL; // 'this' context for function, null in this case + let arg_js = to_value(&round).unwrap(); + + // Call the function + let _ = callback.call1(&this, &arg_js); + } + }); + } + + #[wasm_bindgen] + pub async fn stop(&self) -> Result<(), JsValue> { + self.rustlink + .stop() + .await + .map_err(|e| JsValue::from_str(&format!("Shutdown error: {}", e))) } } diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs index a923716..8a8bed6 100644 --- a/src/fetcher/mod.rs +++ b/src/fetcher/mod.rs @@ -1,3 +1,8 @@ +use std::time::Duration; + +use async_std::stream::StreamExt; +use futures::{select, FutureExt}; + use super::interface::{ChainlinkContract, Round}; use crate::config::Reflector::Sender; use crate::config::{Configuration, Rustlink}; @@ -16,41 +21,46 @@ async fn fetch_round_data_for_contract( // The function signature looks good, but ensure all types (Rustlink, Round, etc.) are properly defined. pub async fn fetch_rounds(rustlink: Rustlink) { let contracts = &rustlink.configuration.contracts; + let mut shutdown_future = rustlink.termination_recv.recv().fuse(); + let worker_future = workflow_rs::core::task::interval(Duration::from_secs( + rustlink.configuration.fetch_interval_seconds, + )); + futures::pin_mut!(worker_future); // This loop runs indefinitely, fetching price data. loop { - for contract_configuration in contracts { - let identifier = &contract_configuration.0; // This variable wasn't used in your original code. - let address = &contract_configuration.1; - - // Fetch price data and attempt to send it via the channel. - match fetch_round_data_for_contract(&rustlink.configuration, identifier, address).await - { - Ok(price_data) => { - match rustlink.reflector { - Sender(ref sender) => { - // Attempt to send the PriceData through the channel. - if let Err(error) = sender.send(price_data).await { - log::error!("Failed sending data: {}", error); + + + for contract_configuration in contracts { + select! { + _ = shutdown_future => { + rustlink.shutdown_send.send(()).await.unwrap(); + return; + }, + _ = worker_future.next().fuse() => { + + let identifier = &contract_configuration.0; // This variable wasn't used in your original code. + let address = &contract_configuration.1; + + // Fetch price data and attempt to send it via the channel. + match fetch_round_data_for_contract(&rustlink.configuration, identifier, address).await + { + Ok(price_data) => { + match rustlink.reflector { + Sender(ref sender) => { + // Attempt to send the PriceData through the channel. + if let Err(error) = sender.send(price_data).await { + log::error!("Failed sending data: {}", error); + } } } } - } - Err(error) => { - log::error!("Failed updating price: {}", error); + Err(error) => { + log::error!("Failed updating price: {}", error); + } } } - - // Wait for the specified interval before fetching the next price. - tokio::time::sleep(std::time::Duration::from_secs( - rustlink.configuration.fetch_interval_seconds, - )) - .await; + } } - - // Depending on your intention, you might not need this additional sleep here because - // the loop itself already waits after each contract is fetched, which might be enough. - // If you wish all contracts to be fetched at once and then wait, keep this. - // Otherwise, it might cause longer than expected delays between fetches. } } diff --git a/src/lib.rs b/src/lib.rs index ce4d491..0931ea5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ mod tests { let (sender, receiver) = unbounded(); - let crypto_prices = Rustlink::try_new( + let rustlink = Rustlink::try_new( "https://bsc-dataseed1.binance.org/", 1, Reflector::Sender(sender), @@ -28,7 +28,7 @@ mod tests { ) .unwrap(); - crypto_prices.fetch(); + rustlink.start(); let round_data = receiver.recv().await.unwrap(); println!("Received data: {:#?}", round_data); assert!(round_data.answer.ge(&0f64)); diff --git a/web-build.sh b/web-build.sh new file mode 100755 index 0000000..a34fa9d --- /dev/null +++ b/web-build.sh @@ -0,0 +1 @@ +wasm-pack build --target web --out-name rustlink --out-dir js/web --dev \ No newline at end of file From cb75285fd1bfca022b74adeb8089eb308fc50d81 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Wed, 15 May 2024 17:44:51 +0200 Subject: [PATCH 09/16] Format --- src/fetcher/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs index 8a8bed6..f295a8a 100644 --- a/src/fetcher/mod.rs +++ b/src/fetcher/mod.rs @@ -29,9 +29,7 @@ pub async fn fetch_rounds(rustlink: Rustlink) { // This loop runs indefinitely, fetching price data. loop { - - - for contract_configuration in contracts { + for contract_configuration in contracts { select! { _ = shutdown_future => { rustlink.shutdown_send.send(()).await.unwrap(); From 8acc1024b159d45b34262ddd71b905cadf92ece9 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 02:41:56 +0200 Subject: [PATCH 10/16] Formatting --- Cargo.lock | 1 + Cargo.toml | 2 ++ js/index.html | 9 +++------ src/config.rs | 8 ++++++-- src/interface/mod.rs | 3 +++ src/lib.rs | 1 - 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acfc43f..a2d2113 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3013,6 +3013,7 @@ dependencies = [ "tokio", "wasm-bindgen", "wasm-bindgen-futures", + "web-sys", "workflow-rs", ] diff --git a/Cargo.toml b/Cargo.toml index 8bbad8c..b913a3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ serde = "1.0.201" thiserror = "1.0.60" workflow-rs = { version = "0.12.1", features = ["full"] } + # Async-std included for all builds async-std = "1.12.0" wasm-bindgen = "0.2.92" @@ -19,6 +20,7 @@ js-sys = "0.3.69" wasm-bindgen-futures = "0.4.42" serde-wasm-bindgen = "0.6.5" futures = "0.3.30" +web-sys = "0.3.69" # Dependencies for non-WASM targets [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/js/index.html b/js/index.html index bf5cf1b..9c2e458 100644 --- a/js/index.html +++ b/js/index.html @@ -26,12 +26,9 @@ rustlink.start(); console.log("Stopping after 5 seconds") - - setTimeout(async ()=>{ - console.log("Stopping..."); - await rustlink.stop(); - console.log("Stopped"); - },5000) + setTimeout(() => { + rustlink.stop(); + }, 5000); } runWasm(); diff --git a/src/config.rs b/src/config.rs index 4592ccf..61ea739 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,11 +7,10 @@ use async_std::channel::{unbounded, Receiver, RecvError, Sender}; use js_sys::Function; use reqwest::{Client, Url}; use serde_wasm_bindgen::{from_value, to_value}; +use workflow_rs::core::cfg_if; use std::str::FromStr; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_bindgen_futures::spawn_local; -use workflow_rs::core::cfg_if; - #[derive(Clone)] pub struct Configuration { pub fetch_interval_seconds: u64, @@ -91,6 +90,7 @@ impl Rustlink { reflector: Reflector, contracts: Vec<(String, String)>, ) -> Result { + let provider = ProviderBuilder::new().on_http(Url::from_str(rpc_url).unwrap()); let (termination_send, termination_recv) = unbounded::<()>(); let (shutdown_send, shutdown_recv) = unbounded::<()>(); @@ -114,6 +114,8 @@ impl Rustlink { #[cfg(target_arch = "wasm32")] async_std::task::block_on(fetch_rounds(self.clone())); + + } pub async fn stop(&self) -> Result<(), RecvError> { @@ -163,6 +165,8 @@ impl RustlinkJS { contracts: Contracts, callback: Function, ) -> Self { + + // Cast `JsValue` to `Function` let contracts: Vec<(String, String)> = from_value(contracts.into()).unwrap(); diff --git a/src/interface/mod.rs b/src/interface/mod.rs index bdd15dd..ef9e09b 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -6,6 +6,8 @@ use serde::{Deserialize, Serialize}; use self::IAggregatorV3Interface::IAggregatorV3InterfaceInstance; + + sol!( #[allow(missing_docs)] #[sol(rpc)] @@ -20,6 +22,7 @@ pub struct ChainlinkContract<'a> { pub decimals: u8, } + /// The latest price received for this symbol. /// This data is directly retrieved from the underlying contract. #[derive(Deserialize, Serialize, Debug, Clone)] diff --git a/src/lib.rs b/src/lib.rs index 0931ea5..655b1dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ pub mod config; mod error; mod fetcher; mod interface; - #[cfg(test)] mod tests { From d7911a841f682824668bd7fb2025f1ead89bebdc Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 13:24:25 +0200 Subject: [PATCH 11/16] Create rust.yml --- .github/workflows/rust.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..9fd45e0 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose From 8016a4b0cfdc9f1bf1784f55bbcc96a405629a04 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 13:41:27 +0200 Subject: [PATCH 12/16] Update readme --- Cargo.lock | 2 +- Cargo.toml | 3 +-- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/config.rs | 35 ++++++++++++++++++------- 4 files changed, 98 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a2d2113..8d5a9ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2998,7 +2998,7 @@ dependencies = [ [[package]] name = "rustlink" -version = "0.1.0" +version = "0.0.1" dependencies = [ "alloy", "async-std", diff --git a/Cargo.toml b/Cargo.toml index b913a3a..ba5e782 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustlink" -version = "0.1.0" +version = "0.0.1" edition = "2021" [dependencies] @@ -12,7 +12,6 @@ serde = "1.0.201" thiserror = "1.0.60" workflow-rs = { version = "0.12.1", features = ["full"] } - # Async-std included for all builds async-std = "1.12.0" wasm-bindgen = "0.2.92" diff --git a/README.md b/README.md index 7a84795..7d23326 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,70 @@ -# `rustlink` - A lightweight rust library for periodically retrieving cryptocurrency prices from the ChainLink decentralized price feed. +# `rustlink` - Decentralized Cryptocurrency Price Feed + +A lightweight rust library for periodically retrieving cryptocurrency prices from the ChainLink decentralized price feed. With `rustlink`, you can easily retrieve the latest price of any cryptocurrency supported by ChainLink. + +## Features +- Retrieve the latest price of any cryptocurrency supported by ChainLink. +- WASM-compatible, so you can use it in your web applications. +- Lightweight and easy to use. +- Customizable update interval for rate limiting. +- Add any custom contract list. +- Customizable RPC url. + +## Why `rustlink`? + +The core principle I have maintained while developing this library is robustness and simplicity. As Web3-developers, payment operators we often need to retrieve cryptocurrency prices. However, most of the libraries available use centralized exchange APIs that have shown to be unreliable and are affected by local exchange fluctuations. Using the ChainLink dencetralized data feed we can retrieve reliable data that is provided by many independent oracles. + +The library is made to be WASM-compatible, so you can use it in your web applications as well. This allows you to receive decentralized price updates in real-time in your web and desktop apps, without having to rely on centralized price feeds or APIs. + +To see which cryptocurrencies are supported by ChainLink, you can visit the [ChainLink data feeds list](https://data.chain.link/feeds). + +## What is WASM? +WebAssembly (WASM) is a binary instruction format for a stack-based virtual machine. WASM is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications. WASM is supported by all major browsers, including Chrome, Firefox, Safari, and Edge. + +This means that you can run rust code in your web applications, and use `rustlink` to retrieve cryptocurrency prices in real-time in your web apps. + +## Installation +To use `rustlink` in your project, add the following to your `Cargo.toml` file: + +```toml +[dependencies] +rustlink = "0.0.1" +``` + +## Usage +Here is a simple example of how you can use `rustlink` to retrieve the latest price of a cryptocurrency: + +```rust +use async_std::channel::unbounded; +use rustlink::config::{Reflector, Rustlink}; + +#[tokio::main] +async fn main(){ + let mut contracts: Vec<(String, String)> = Vec::new(); + contracts.push(( + "ETH".to_string(),"0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string(), + )); + + let (sender, receiver) = unbounded(); + + let rustlink = Rustlink::try_new( + "https://bsc-dataseed1.binance.org/", + 1, + Reflector::Sender(sender), + contracts, + ) + .unwrap(); + rustlink.start(); + let round_data = receiver.recv().await.unwrap(); + println!("Received data: {:#?}", round_data); +} +``` + +You can also loop through the `receiver` to get the latest price updates in real-time by putting the receiver in a loop: + +```rust +loop { + let round_data = receiver.recv().await.unwrap(); + println!("Received data: {:#?}", round_data); +} +``` \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 61ea739..8bdabb3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,16 +73,33 @@ impl Rustlink { /// Example: /// /// ```rust - /// use rustlink::config::Rustlink; /// use async_std::channel::unbounded; - /// use rustlink::config::Reflector; - /// let mut contracts:Vec<(String,String)>=Vec::new(); - /// contracts.push(("BTC".to_string(),"0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string())); - /// - /// let (sender, receiver) = unbounded(); - /// - /// let reflector=Reflector::Sender(sender);/// - /// let crypto_prices=Rustlink::try_new("https://bsc-dataseed1.binance.org/",10,reflector,contracts); + /// use rustlink::config::{Reflector, Rustlink}; + /// + /// #[tokio::main] + /// + /// async fn main(){ + /// let mut contracts: Vec<(String, String)> = Vec::new(); + /// contracts.push(( + /// "ETH".to_string(), + /// "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e".to_string(), + /// )); + /// + /// let (sender, receiver) = unbounded(); + /// + /// let rustlink = Rustlink::try_new( + /// "https://bsc-dataseed1.binance.org/", + /// 1, + /// Reflector::Sender(sender), + /// contracts, + /// ) + /// .unwrap(); + /// rustlink.start(); + /// let round_data = receiver.recv().await.unwrap(); + /// println!("Received data: {:#?}", round_data); + /// } + /// + /// /// ``` pub fn try_new( rpc_url: &str, From dcebaf0af1ec77b7601b983404073e1cfd333fcb Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 14:12:29 +0200 Subject: [PATCH 13/16] Add metadata and WASM usage in README --- Cargo.toml | 5 +++ README.md | 63 +++++++++++++++++++++++++++++++++ src/fetcher/mod.rs | 4 +-- src/lib.rs | 4 +-- src/{config.rs => rustlink.rs} | 64 ++++++++++++++++++++++++++++------ 5 files changed, 126 insertions(+), 14 deletions(-) rename src/{config.rs => rustlink.rs} (71%) diff --git a/Cargo.toml b/Cargo.toml index ba5e782..1b4a35f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,11 @@ name = "rustlink" version = "0.0.1" edition = "2021" +license = "MIT OR Apache-2.0" +description = "A lightweight and easy-to-use library for periodically retrieving data from the Chainlink decentralized data feed." +repository = "https://github.com/starkbamse/rustlink" +include = ["**/*.json"] +keywords = ["crypto", "cryptocurrencies","chainlink","prices"] [dependencies] log = "0.4.21" diff --git a/README.md b/README.md index 7d23326..811313b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,37 @@ To use `rustlink` in your project, add the following to your `Cargo.toml` file: rustlink = "0.0.1" ``` +## Build for WASM + +1. ### Prerequisites + To build the library for WASM, you need to have the `wasm-pack` tool installed. You can install it by running the following command: + + ```bash + cargo install wasm-pack + ``` + + You also need the wasm32-unknown-unknown target installed. You can install it by running the following command: + + ```bash + rustup target add wasm32-unknown-unknown + ``` + +2. ### Building WASM + You can build the library either for the **browser** or for **Node.js**. + + **For the browser:** + + ```bash + ./web-build.sh + ``` + + **For Node.js:** + + ```bash + ./node-build.sh + ``` + + ## Usage Here is a simple example of how you can use `rustlink` to retrieve the latest price of a cryptocurrency: @@ -67,4 +98,36 @@ loop { let round_data = receiver.recv().await.unwrap(); println!("Received data: {:#?}", round_data); } +``` + +## WASM Usage + +```javascript +import init, { RustlinkJS } from '../web/rustlink.js'; + +async function runWasm() { + await init(); // Initialize the wasm module + + // Example data + const rpcUrl = "https://bsc-dataseed1.binance.org/"; + const fetchIntervalSeconds = BigInt(1); + const contracts = [ + ["ETH", "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e"], + ["1INCH", "0x9a177Bb9f5b6083E962f9e62bD21d4b5660Aeb03"], + ]; + + async function callback(roundData) { + console.log("Callback received:", roundData); + } + + let rustlink = new RustlinkJS(rpcUrl, fetchIntervalSeconds, contracts, callback); + + rustlink.start(); + console.log("Stopping after 5 seconds"); + setTimeout(() => { + rustlink.stop(); + }, 5000); +} + +runWasm(); ``` \ No newline at end of file diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs index f295a8a..8b9d082 100644 --- a/src/fetcher/mod.rs +++ b/src/fetcher/mod.rs @@ -4,8 +4,8 @@ use async_std::stream::StreamExt; use futures::{select, FutureExt}; use super::interface::{ChainlinkContract, Round}; -use crate::config::Reflector::Sender; -use crate::config::{Configuration, Rustlink}; +use crate::rustlink::Reflector::Sender; +use crate::rustlink::{Configuration, Rustlink}; /// Retrieves the price of an underlying asset from a particular contract async fn fetch_round_data_for_contract( diff --git a/src/lib.rs b/src/lib.rs index 655b1dc..efb46f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -pub mod config; +pub mod rustlink; mod error; mod fetcher; mod interface; @@ -7,7 +7,7 @@ mod tests { use async_std::channel::unbounded; - use crate::config::{Reflector, Rustlink}; + use crate::rustlink::{Reflector, Rustlink}; #[tokio::test] async fn ensure_price_is_received() { diff --git a/src/config.rs b/src/rustlink.rs similarity index 71% rename from src/config.rs rename to src/rustlink.rs index 8bdabb3..28963a1 100644 --- a/src/config.rs +++ b/src/rustlink.rs @@ -11,6 +11,12 @@ use workflow_rs::core::cfg_if; use std::str::FromStr; use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_bindgen_futures::spawn_local; + +/// ## Configuration +/// This struct contains the configuration for Rustlink. It contains the following fields: +/// - `fetch_interval_seconds`: How often to update data points (to prevent RPC rate limitation) +/// - `contracts`: A list of tuples containing a ticker name and its corresponding contract address on the EVM chain +/// - `provider`: The provider to use for fetching data #[derive(Clone)] pub struct Configuration { pub fetch_interval_seconds: u64, @@ -18,15 +24,12 @@ pub struct Configuration { pub provider: RootProvider>, } -/// ## Rustlink +/// ## Rustlink instance. This is the main struct that you will interact with. /// /// Rustlink is a lightweight Rust library that provides your Rust applications with a direct /// link to the latest cryptocurrency prices. All data is retrieved from Chainlink decentralized /// price feeds. Just copy the contract addresses for the symbol that you would like to track from: -/// https://data.chain.link/feeds. -/// /// -/// Note: Rustlink is designed to be ran on the main thread, in an asynchronous tokio environment #[derive(Clone)] pub struct Rustlink { pub configuration: Configuration, @@ -64,7 +67,6 @@ impl Rustlink { /// /// Expected parameters: /// - `rpc_url`: The RPC url of your chosen EVM network where Chainlink offers decentralised data feeds. - /// Don't know where? Check https://data.chain.link/feeds. /// - `fetch_interval_seconds`: How often to update data points in the database (to prevent RPC rate limitation) /// - `reflector`: How you choose to receive the answer from your provided contracts. /// - `contracts`: A tuple list containing a ticker name and its corresponding contract address on the @@ -98,8 +100,6 @@ impl Rustlink { /// let round_data = receiver.recv().await.unwrap(); /// println!("Received data: {:#?}", round_data); /// } - /// - /// /// ``` pub fn try_new( rpc_url: &str, @@ -125,21 +125,26 @@ impl Rustlink { }) } + /// Starts the Rustlink instance. + /// This method will start fetching the latest price data from the Chainlink decentralized data feed. pub fn start(&self) { #[cfg(not(target_arch = "wasm32"))] tokio::task::spawn(fetch_rounds(self.clone())); #[cfg(target_arch = "wasm32")] async_std::task::block_on(fetch_rounds(self.clone())); - - } + /// Stops the Rustlink instance. + /// This method will stop fetching the latest price data from the Chainlink decentralized data feed. pub async fn stop(&self) -> Result<(), RecvError> { self.termination_send.send(()).await.unwrap(); self.shutdown_recv.recv().await } } + +/// RustlinkJS is a JavaScript wrapper for Rustlink. +/// It allows you to create a Rustlink instance in JavaScript and start fetching data when you use WASM. #[wasm_bindgen] pub struct RustlinkJS { rustlink: Rustlink, @@ -174,7 +179,41 @@ extern "C" { #[wasm_bindgen] impl RustlinkJS { - /// Creates a new RustlinkJS instance + /// Creates a new RustlinkJS instance. + /// Expected parameters: + /// - `rpc_url`: The RPC url of your chosen EVM network where Chainlink offers decentralised data feeds. + /// - `fetch_interval_seconds`: How often to update data points (to prevent RPC rate limitation) + /// - `contracts`: A list of tuples containing a ticker name and its corresponding contract address on the EVM chain + /// - `callback`: A JavaScript function (async or sync) that will be called every time a new data point is fetched + /// ```javascript + /// import init, { RustlinkJS } from '../web/rustlink.js'; + /// + /// async function runWasm() { + /// await init(); // Initialize the wasm module + /// + /// // Example data + /// const rpcUrl = "https://bsc-dataseed1.binance.org/"; + /// const fetchIntervalSeconds = BigInt(1); + /// const contracts = [ + /// ["ETH", "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2e"], + /// ["1INCH", "0x9a177Bb9f5b6083E962f9e62bD21d4b5660Aeb03"], + /// ]; + /// + /// async function callback(roundData) { + /// console.log("Callback received:", roundData); + /// } + /// + /// let rustlink = new RustlinkJS(rpcUrl, fetchIntervalSeconds, contracts, callback); + /// + /// rustlink.start(); + /// console.log("Stopping after 5 seconds"); + /// setTimeout(() => { + /// rustlink.stop(); + /// }, 5000); + /// } + /// + /// runWasm(); + /// ``` #[wasm_bindgen(constructor)] pub fn new( rpc_url: &str, @@ -200,6 +239,9 @@ impl RustlinkJS { receiver, } } + + /// Starts the RustlinkJS instance. + /// This method will start fetching the latest price data from the Chainlink decentralized data feed. #[wasm_bindgen] pub fn start(&self) { self.rustlink.start(); @@ -217,6 +259,8 @@ impl RustlinkJS { }); } + /// Stops the RustlinkJS instance. + /// This method will stop fetching the latest price data from the Chainlink decentralized data feed. #[wasm_bindgen] pub async fn stop(&self) -> Result<(), JsValue> { self.rustlink From 2039563360a55c696fe575c51645b390f9506707 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 14:14:37 +0200 Subject: [PATCH 14/16] Delete js folder --- js/index.html | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 js/index.html diff --git a/js/index.html b/js/index.html deleted file mode 100644 index 9c2e458..0000000 --- a/js/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - Rust WASM Example - - - -

Check the console for output

- - \ No newline at end of file From 76a00e5df83de8988d3e04b657250d8efb311a8c Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 14:14:53 +0200 Subject: [PATCH 15/16] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6953c19..8ac268a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ rustlink.log /target +/js \ No newline at end of file From 1719505eaf9a494b6924efbd5e3c0958729328b4 Mon Sep 17 00:00:00 2001 From: starkbamse <139136798+starkbamse@users.noreply.github.com> Date: Thu, 16 May 2024 14:18:15 +0200 Subject: [PATCH 16/16] Update module name --- src/{rustlink.rs => core.rs} | 4 ++-- src/fetcher/mod.rs | 4 ++-- src/lib.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/{rustlink.rs => core.rs} (99%) diff --git a/src/rustlink.rs b/src/core.rs similarity index 99% rename from src/rustlink.rs rename to src/core.rs index 28963a1..12fb026 100644 --- a/src/rustlink.rs +++ b/src/core.rs @@ -47,7 +47,7 @@ pub struct Rustlink { /// which you can create by doing: /// ```rust /// use async_std::channel::unbounded; -/// use rustlink::config::Reflector; +/// use rustlink::core::Reflector; /// /// let (sender, receiver) = unbounded(); /// @@ -76,7 +76,7 @@ impl Rustlink { /// /// ```rust /// use async_std::channel::unbounded; - /// use rustlink::config::{Reflector, Rustlink}; + /// use rustlink::core::{Reflector, Rustlink}; /// /// #[tokio::main] /// diff --git a/src/fetcher/mod.rs b/src/fetcher/mod.rs index 8b9d082..d3244eb 100644 --- a/src/fetcher/mod.rs +++ b/src/fetcher/mod.rs @@ -4,8 +4,8 @@ use async_std::stream::StreamExt; use futures::{select, FutureExt}; use super::interface::{ChainlinkContract, Round}; -use crate::rustlink::Reflector::Sender; -use crate::rustlink::{Configuration, Rustlink}; +use crate::core::Reflector::Sender; +use crate::core::{Configuration, Rustlink}; /// Retrieves the price of an underlying asset from a particular contract async fn fetch_round_data_for_contract( diff --git a/src/lib.rs b/src/lib.rs index efb46f7..fef554b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -pub mod rustlink; +pub mod core; mod error; mod fetcher; mod interface; @@ -7,7 +7,7 @@ mod tests { use async_std::channel::unbounded; - use crate::rustlink::{Reflector, Rustlink}; + use crate::core::{Reflector, Rustlink}; #[tokio::test] async fn ensure_price_is_received() {