diff --git a/.gitignore b/.gitignore index f2b1f66..252d7f9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,6 @@ /target/ **/target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..657653d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4075 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "alloy" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59febb24956a41c29bb5f450978fbe825bd6456b3f80586c8bd558dc882e7b6a" +dependencies = [ + "alloy-consensus", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-json-rpc", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", +] + +[[package]] +name = "alloy-chains" +version = "0.1.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88e1edea70787c33e11197d3f32ae380f3db19e6e061e539a5bcf8184a6b326" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "auto_impl", + "c-kzg", + "derive_more 1.0.0", + "serde", +] + +[[package]] +name = "alloy-consensus-any" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b1bb53f40c0273cd1975573cd457b39213e68584e36d1401d25fd0398a1d65" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-core" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f1ab91967646311bb7dd32db4fee380c69fe624319dcd176b89fb2a420c6b5" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf69d3061e2e908a4370bda5d8d6529d5080232776975489eec0b49ce971027e" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow", +] + +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c986539255fb839d1533c128e190e557e52ff652c9ef62939e233a81dd93f7e" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more 1.0.0", + "serde", +] + +[[package]] +name = "alloy-eips" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9fadfe089e9ccc0650473f2d4ef0a28bc015bbca5631d9f0f09e49b557fdb3" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "derive_more 1.0.0", + "once_cell", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2a4cf7b70f3495788e74ce1c765260ffe38820a2a774ff4aacb62e31ea73f9" +dependencies = [ + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4584e3641181ff073e9d5bec5b3b8f78f9749d9fb108a1cfbc4399a4a139c72a" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e29040b9d5fe2fb70415531882685b64f8efd08dfbd6cc907120650504821105" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510cc00b318db0dfccfdd2d032411cfae64fc144aef9679409e014145d3dacc4" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9081c099e798b8a2bba2145eb82a9a146f01fc7a35e9ab6e7b43305051f97550" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777d58b30eb9a4db0e5f59bc30e8c2caef877fee7dc8734cf242a51a60f22e05" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.0.1", + "foldhash", + "hashbrown 0.15.5", + "indexmap", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2dfaddd9a30aa870a78a4e1316e3e115ec1e12e552cbc881310456b85c1f24" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "futures-utils-wasm", + "lru", + "parking_lot", + "pin-project", + "reqwest", + "schnellru", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531137b283547d5b9a5cafc96b006c64ef76810c681d606f28be9781955293b6" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3410a472ce26c457e9780f708ee6bd540b30f88f1f31fdab7a11d00bd6aa1aee" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-any" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed98e1af55a7d856bfa385f30f63d8d56be2513593655c904a8f4a7ec963aa3e" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth", + "alloy-serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8737d7a6e37ca7bba9c23e9495c6534caec6760eb24abc9d5ffbaaba147818e1" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "derive_more 1.0.0", + "itertools 0.13.0", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5851bf8d5ad33014bd0c45153c603303e730acc8a209450a7ae6b4a12c2789e2" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e10ca565da6500cca015ba35ee424d59798f2e1b85bc0dd8f81dafd401f029a" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror 2.0.17", +] + +[[package]] +name = "alloy-signer-local" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47fababf5a745133490cde927d48e50267f97d3d1209b9fc9f1d1d666964d172" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand 0.8.5", + "thiserror 2.0.17", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e68b32b6fa0d09bb74b4cefe35ccc8269d711c26629bc7cd98a47eeb12fe353f" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2afe6879ac373e58fd53581636f2cce843998ae0b058ebe1e4f649195e2bd23c" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck", + "indexmap", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.108", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ba01aee235a8c699d07e5be97ba215607564e71be72f433665329bec307d28" +dependencies = [ + "const-hex", + "dunce", + "heck", + "macro-string", + "proc-macro2", + "quote", + "syn 2.0.108", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c13fc168b97411e04465f03e632f31ef94cad1c7c8951bf799237fd7870d535" +dependencies = [ + "serde", + "winnow", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e960c4b52508ef2ae1e37cae5058e905e9ae099b107900067a503f8c454036f" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "538a04a37221469cac0ce231b737fd174de2fdfcdd843bdd068cb39ed3e066ad" +dependencies = [ + "alloy-json-rpc", + "base64", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ed40eb1e1265b2911512f6aa1dcece9702d078f5a646730c45e39e2be00ac1c" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-trie" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a94854e420f07e962f7807485856cde359ab99ab6413883e15235ad996e8b" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "arrayvec", + "derive_more 1.0.0", + "nybbles", + "serde", + "smallvec", + "tracing", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[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.1", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "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-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.108", +] + +[[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-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[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-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +dependencies = [ + "serde", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + +[[package]] +name = "cc" +version = "1.2.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "color-eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "const-hex" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +dependencies = [ + "cfg-if", + "cpufeatures", + "proptest", + "serde_core", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl 2.0.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[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 = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[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.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[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.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "hyperprocess_macro" +version = "0.1.0" +dependencies = [ + "hyperware_process_lib", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "hyperware_process_lib" +version = "2.2.0" +source = "git+https://github.com/hyperware-ai/process_lib?rev=d3bb304#d3bb30404fd94cffa473e4fc2503bbeed7dc1c4f" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "base64", + "bincode", + "color-eyre", + "futures-channel", + "futures-util", + "http", + "mime_guess", + "rand 0.8.5", + "regex", + "rmp-serde", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", + "tracing-error", + "tracing-subscriber", + "url", + "uuid", + "wit-bindgen 0.42.1", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", + "serde", + "serde_core", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[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.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "nybbles" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +dependencies = [ + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "openssl" +version = "0.10.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" +dependencies = [ + "bitflags", + "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.108", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "owo-colors" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.108", +] + +[[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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "reqwest" +version = "0.12.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +dependencies = [ + "base64", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[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 = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "ruint" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand 0.8.5", + "rand 0.9.2", + "rlp", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.27", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "schnellru" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +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.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4e6eed052a117409a1a744c8bda9c3ea6934597cf7419f791cb7d590871c4c" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[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 = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen 0.46.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.108", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.230.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4349d0943718e6e434b51b9639e876293093dca4b96384fb136ab5bd5ce6660" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.230.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a52e010df5494f4289ccc68ce0c2a8c17555225a5e55cc41b98f5ea28d0844b" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.230.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808198a69b5a0535583370a51d459baa14261dfab04800c4864ee9e1a14346ed" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver 1.0.27", +] + +[[package]] +name = "wasmtimer" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa5b79cd8cb4b27a9be3619090c03cbb87fe7b1c6de254b4c9b4477188828af8" +dependencies = [ + "wit-bindgen-rt", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "wit-bindgen-core" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35e550f614e16db196e051d22b0d4c94dd6f52c90cb1016240f71b9db332631" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051105bab12bc78e161f8dfb3596e772dd6a01ebf9c4840988e00347e744966a" +dependencies = [ + "bitflags", + "futures", + "once_cell", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb1e0a91fc85f4ef70e0b81cd86c2b49539d3cd14766fd82396184aadf8cb7d7" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.108", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce69f52c5737705881d5da5a1dd06f47f8098d094a8d65a3e44292942edb571f" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.108", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.230.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b607b15ead6d0e87f5d1613b4f18c04d4e80ceeada5ffa608d8360e6909881df" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.230.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679fde5556495f98079a8e6b9ef8c887f731addaffa3d48194075c1dd5cd611b" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver 1.0.27", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +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.108", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..543b1ab --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hyperprocess_macro" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["full", "extra-traits"] } + +hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", features = ["hyperapp"], rev = "d3bb304" } diff --git a/README.md b/README.md index d81c270..230428a 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,9 @@ struct MyProcessState { name = "My Process", ui = Some(HttpBindingConfig::default()), endpoints = vec![ - Binding::Http { - path: "/api", - config: HttpBindingConfig::new(false, false, false, None) + Binding::Http { + path: "/api", + config: HttpBindingConfig::new(false, false, false, None) } ], save_config = SaveOptions::EveryMessage, @@ -85,7 +85,7 @@ impl MyProcessState { async fn initialize(&mut self) { // Initialize your process } - + #[http] async fn handle_http_request(&mut self, value: String) -> String { self.counter += 1; @@ -135,13 +135,14 @@ Example: ### Handler Types -Hyperware processes can handle three types of requests, specified by attributes: +Hyperware processes can handle four types of requests, specified by attributes: | Attribute | Description | |-----------|-------------| | `#[local]` | Handles local (same-node) requests | | `#[remote]` | Handles remote (cross-node) requests | | `#[http]` | Handles ALL HTTP requests (GET, POST, PUT, DELETE, etc.) | +| `#[eth]` | Handles Ethereum subscription updates from your RPC provider | These attributes can be combined to make a handler respond to multiple request types: @@ -216,14 +217,14 @@ fn handle_any_method(&mut self) -> Response { **Supported Methods**: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS` -### Smart Routing System +### Smart Routing System The framework uses intelligent priority-based routing that automatically chooses the best handler based on the request: #### **Priority Logic:** 1. **Has Request Body** → Tries parameterized handlers first - - Deserializes body to determine the correct handler + - Deserializes body to determine the correct handler - Falls back to parameter-less handlers if deserialization fails 2. **No Request Body** → Tries parameter-less handlers first @@ -238,7 +239,7 @@ The framework uses intelligent priority-based routing that automatically chooses #[http(method = "GET", path = "/health")] fn health_check(&mut self) -> &'static str { "OK" } -#[http(method = "DELETE", path = "/api/users")] +#[http(method = "DELETE", path = "/api/users")] fn delete_all_users(&mut self) -> Result { // DELETE requests typically have no body self.users.clear(); @@ -276,10 +277,10 @@ async fn async_handler(&mut self, data: MyData) -> Result { // get_path() and get_http_method() work correctly in async handlers! let path = get_path().unwrap_or_default(); let method = get_http_method().unwrap_or_default(); - + // Make async calls to other services let result = external_api_call(data).await?; - + Ok(format!("Processed {} {} with result: {}", method, path, result)) } ``` @@ -289,7 +290,7 @@ async fn async_handler(&mut self, data: MyData) -> Result { ```rust // Request: POST /api/upload (with body) // 1. ✅ Tries: create_item handler if body matches {"CreateItem": ...} -// 2. ✅ Tries: update_settings handler if body matches {"UpdateSettings": ...} +// 2. ✅ Tries: update_settings handler if body matches {"UpdateSettings": ...} // 3. ✅ Falls back to: handle_post_with_data for unmatched bodies // 4. ✅ Ultimate fallback: handle_any_method @@ -318,7 +319,7 @@ impl MyApp { // This handler ONLY responds to GET /api/users self.users.clone() } - + // Handler with parameters (path optional but recommended) #[http(method = "POST", path = "/api/users")] fn create_user(&mut self, user: NewUser) -> User { @@ -327,14 +328,14 @@ impl MyApp { self.users.push(user.clone()); user } - + // Parameter-less handler accepting all methods (path optional) #[http(path = "/api/status")] fn api_status(&mut self) -> Status { // This handles ALL methods to /api/status Status { healthy: true } } - + // Parameter-less handler for any path - uses get_path() for routing #[http] fn dynamic_handler(&mut self) -> Response { @@ -344,7 +345,7 @@ impl MyApp { _ => Response::not_found("Unknown endpoint") } } - + // Handler with parameters without specific path #[http(method = "POST")] fn generic_post_handler(&mut self, data: GenericData) -> Response { @@ -366,7 +367,9 @@ impl MyApp { - All handler names must be unique when converted to CamelCase (e.g., `get_user` and `get_user` conflict) - Init methods must be async and take only `&mut self` - WebSocket methods must have exactly 3 parameters: `channel_id: u32`, `message_type: WsMessageType`, `blob: LazyLoadBlob` -- At least one handler must be defined (`#[http]`, `#[local]`, or `#[remote]`) +- ETH handlers must take exactly 1 parameter: `eth_sub_result: EthSubResult` +- Only one ETH handler is allowed per hyperprocess +- At least one handler must be defined (`#[http]`, `#[local]`, `#[remote]`, or `#[eth]`) - The macro provides comprehensive error messages with debugging tips for all validation failures **Current Limitations**: @@ -389,17 +392,136 @@ async fn initialize(&mut self) { #### WebSocket Handler -For defining a `ws` endpoint, do: +For defining a `ws` endpoint (server-side WebSocket), do: ```rust +// Synchronous WebSocket handler #[ws] fn handle_websocket(&mut self, channel_id: u32, message_type: WsMessageType, blob: LazyLoadBlob) { - // Process WebSocket messages + // Process WebSocket messages from connected clients +} + +// Asynchronous WebSocket handler +#[ws] +async fn handle_websocket_async(&mut self, channel_id: u32, message_type: WsMessageType, blob: LazyLoadBlob) { + // Process WebSocket messages asynchronously + // Can make async calls to other services + let result = some_async_operation().await; } ``` -if you have multiple ws endpoints, you can match on the ws endpoints with `get_path()`, which will give you an `Option`. -if you want to access the http server, you can call `get_server()`, giving you access to `HttpServer`. +Both sync and async variants are supported. If you have multiple ws endpoints, you can match on the ws endpoints with `get_path()`, which will give you an `Option`. +If you want to access the http server, you can call `get_server()`, giving you access to `HttpServer`. + +#### WebSocket Client Handler + +For handling WebSocket client connections (when your process acts as a WebSocket client), use: + +```rust +// Synchronous WebSocket client handler +#[ws_client] +fn handle_ws_client(&mut self, channel_id: u32, message_type: WsMessageType, blob: LazyLoadBlob) { + match message_type { + WsMessageType::Text | WsMessageType::Binary => { + // Handle incoming message from the WebSocket server + // The blob contains the message data + let data = String::from_utf8_lossy(&blob.bytes); + // Process the message... + }, + WsMessageType::Close => { + // Handle connection close + // blob will be empty for close messages + }, + _ => { + // Handle other message types (Ping/Pong are handled automatically) + } + } +} + +// Asynchronous WebSocket client handler +#[ws_client] +async fn handle_ws_client_async(&mut self, channel_id: u32, message_type: WsMessageType, blob: LazyLoadBlob) { + // Process WebSocket client messages asynchronously + let processed_data = async_process_message(&blob).await; + // Send response back if needed... +} +``` + +Both sync and async variants are supported. This handler receives messages from WebSocket servers that your process has connected to using the `http-client:distro:sys` service. +The signature matches that of `#[ws]` for consistency. + +#### ETH Handler + +For handling Ethereum subscription updates from the `eth:distro:sys` service, use: + +```rust +// Synchronous ETH handler with resubscription +#[eth] +fn handle_eth(&mut self, eth_sub_result: EthSubResult) -> String { + match eth_sub_result { + Ok(eth_sub) => { + // Handle successful subscription update + println!("Got ETH subscription update: id={}, result={:?}", + eth_sub.id, eth_sub.result); + "Subscription update processed".to_string() + } + Err(eth_sub_error) => { + // Handle subscription error with resubscription + println!("ETH subscription error: id={}, error={}", + eth_sub_error.id, eth_sub_error.error); + + // Clean up existing subscription and resubscribe + let _ = self.hypermap.provider.unsubscribe(1); + self.hypermap.provider.subscribe_loop( + 1, + make_filter(&self.hypermap, None), + 0, + 0, + ); + + "ETH subscription error resolved, subscription reinstated".to_string() + } + } +} + +// Asynchronous ETH handler with resubscription +#[eth] +async fn handle_eth_async(&mut self, eth_sub_result: EthSubResult) -> String { + match eth_sub_result { + Ok(eth_sub) => { + // Process subscription update asynchronously + let processed = self.process_eth_event(ð_sub).await; + format!("Processed ETH event: {}", processed) + } + Err(eth_sub_error) => { + // Handle error asynchronously with resubscription + self.log_eth_error(ð_sub_error).await; + + // Clean up existing subscription and resubscribe + let _ = self.hypermap.provider.unsubscribe(1); + self.hypermap.provider.subscribe_loop( + 1, + make_filter(&self.hypermap, None), + 0, + 0, + ); + + "ETH subscription error resolved, subscription reinstated".to_string() + } + } +} +``` + +**Important Notes:** +- Only **one** ETH handler is allowed per hyperprocess +- The handler **must** take exactly one parameter: `eth_sub_result: EthSubResult` +- Both sync and async variants are supported +- The handler receives subscription updates and errors from the ETH module +- `EthSubResult` is a `Result` type where: + - `EthSub` contains subscription updates with `id: u64` and `result: serde_json::Value` + - `EthSubError` contains subscription errors with `id: u64` and `error: String` +- **Resubscription Pattern**: Always unsubscribe first, then resubscribe with current state + ### Binding Endpoints @@ -450,7 +572,7 @@ struct AsyncRequesterState { Binding::Http { path: "/api", config: HttpBindingConfig::new(false, false, false, None), - }, + }, Binding::Ws { path: "/ws", config: WsBindingConfig::new(false, false, false), @@ -527,22 +649,22 @@ fn search(&mut self) -> Vec { if let Some(params) = get_query_params() { // params is a HashMap with: // {"q" => "rust", "limit" => "20", "sort" => "date"} - + // Get search query (with default) let query = params.get("q") .map(|s| s.to_string()) .unwrap_or_else(|| "".to_string()); - + // Parse numeric parameters let limit = params.get("limit") .and_then(|s| s.parse::().ok()) .unwrap_or(10); - + // Get optional parameters let sort_by = params.get("sort") .map(|s| s.as_str()) .unwrap_or("relevance"); - + // Use the parameters self.perform_search(&query, limit, sort_by) } else { @@ -565,7 +687,7 @@ The macro generates detailed logging for all operations: ```rust // Automatically generated logs help track request flow: // Phase 1: Checking parameter-less handlers for path: '/api/users', method: 'GET' -// Successfully parsed HTTP path: '/api/users' +// Successfully parsed HTTP path: '/api/users' // Set current_path to: Some("/api/users") // Set current_http_method to: Some("GET") ``` @@ -574,11 +696,11 @@ The macro generates detailed logging for all operations: ``` // Wrong handler name -Invalid request format. Expected one of the parameterized handler formats, +Invalid request format. Expected one of the parameterized handler formats, but got: {"WrongHandler":{"message":"test"}} // Invalid JSON syntax -Invalid JSON in request body. Expected: {"CreateUser":[ ...parameters... ]}. +Invalid JSON in request body. Expected: {"CreateUser":[ ...parameters... ]}. Parse error: expected value at line 1 column 1 // Empty body for parameterized handler @@ -659,11 +781,11 @@ Content-Type: application/json } // ✅ This works - body must wrap parameters in handler name -POST /api/users +POST /api/users Content-Type: application/json { "CreateUser": { - "name": "John Doe", + "name": "John Doe", "email": "john@example.com" } } @@ -694,11 +816,11 @@ async fn create_user(&mut self, user: User) -> Result { ... } async fn async_handler(&mut self, data: MyData) -> String { // ✅ Works - context is preserved by the framework let path = get_path().unwrap_or_default(); - + // ⚠️ Potential issue - long-running tasks might lose context tokio::time::sleep(Duration::from_secs(30)).await; let path2 = get_path(); // May be None if context expires - + format!("Path: {}", path) } ``` @@ -749,7 +871,7 @@ fn handle_file_upload(&mut self) -> Result { #[http(method = "POST")] fn create_user(&mut self, user: User) -> User { ... } -#[http(method = "PUT")] +#[http(method = "PUT")] fn create_user(&mut self, user: User) -> User { ... } // ERROR: Duplicate CreateUser variant ``` @@ -767,7 +889,7 @@ fn update_user(&mut self, user: User) -> User { ... } fn user_handler(&mut self, user: User) -> User { match get_http_method().as_deref() { Some("POST") => self.create_user_impl(user), - Some("PUT") => self.update_user_impl(user), + Some("PUT") => self.update_user_impl(user), _ => panic!("Unsupported method") } } @@ -810,7 +932,7 @@ fn health_check(&mut self) -> &'static str { "OK" } #[http(method = "POST", path = "/api/users")] async fn create_specific_user(&mut self, user: NewUser) -> User { ... } -// Medium-priority dynamic handlers +// Medium-priority dynamic handlers #[http(method = "POST")] async fn create_general(&mut self, data: CreateData) -> Response { ... } @@ -823,7 +945,7 @@ fn catch_all(&mut self) -> Response { ... } 1. ✅ Matches `health_check` directly (exact path + method) 2. ❌ No body parsing attempted -**Request: `POST /api/users` with body `{"CreateSpecificUser": {...}}`** +**Request: `POST /api/users` with body `{"CreateSpecificUser": {...}}`** 1. ✅ Matches `create_specific_user` (path + method + body deserialization) 2. ❌ No fallback needed @@ -855,7 +977,7 @@ fn health_check(&mut self) -> &'static str { fn api_router(&mut self) -> Response { match (get_http_method().as_deref(), get_path().as_deref()) { (Some("GET"), Some("/api/users")) => self.list_users(), - (Some("GET"), Some("/api/stats")) => self.get_stats(), + (Some("GET"), Some("/api/stats")) => self.get_stats(), _ => Response::not_found("Endpoint not found") } } @@ -894,7 +1016,7 @@ pub enum ApiError { fn validated_handler(&mut self, data: InputData) -> Result { data.validate() .map_err(|e| ApiError::ValidationError(e))?; - + self.process(data) .map_err(|_| ApiError::InternalError) } @@ -908,10 +1030,10 @@ struct MyAppState { // ✅ Use reasonable defaults pub counter: u64, pub users: Vec, - + // ✅ Use Options for optional state pub last_sync: Option, - + // ✅ Group related data pub config: AppConfig, } @@ -922,7 +1044,7 @@ impl MyAppState { self.counter += 1; self.counter } - + fn add_user(&mut self, user: User) -> Result<(), String> { if self.users.iter().any(|u| u.id == user.id) { return Err("User already exists".to_string()); @@ -944,7 +1066,7 @@ async fn fetch_external_data(&mut self, query: String) -> Result &external_service_address(), 10 // timeout in seconds ).await; - + match result { SendResult::Success(response) => Ok(response.data), SendResult::Timeout => Err("Request timed out".to_string()), @@ -974,7 +1096,7 @@ The macro will parse arguments like so: fn parse_args(attr_args: MetaList) -> syn::Result { // Parse attributes like name, icon, endpoints, etc. // Validate required parameters - + Ok(HyperProcessArgs { name: name.ok_or_else(|| syn::Error::new(span, "Missing 'name'"))?, icon, @@ -998,7 +1120,7 @@ fn validate_init_method(method: &syn::ImplItemFn) -> syn::Result<()> { "Init method must be declared as async", )); } - + // Check parameter and return types // ... } @@ -1164,7 +1286,7 @@ where { // Generate unique correlation ID let correlation_id = Uuid::new_v4().to_string(); - + // Send request with correlation ID let _ = Request::to(target) .body(serde_json::to_vec(&message).unwrap()) @@ -1174,7 +1296,7 @@ where // Await response with matching correlation ID let response_bytes = ResponseFuture::new(correlation_id).await; - + // Process response... } ``` @@ -1224,7 +1346,7 @@ loop { APP_CONTEXT.with(|ctx| { ctx.borrow_mut().executor.poll_all_tasks(); }); - + // Wait for next message (blocking) match await_message() { // Process message... @@ -1300,30 +1422,6 @@ enum Response { } ``` -#### Handler Dispatch Generation - -For each handler, the macro generates dispatch code: - -**Async Handler Example**: - -```rust -Request::FetchData(id) => { - let id_captured = id; // Capture parameter before moving - let state_ptr: *mut MyState = state; - - hyper! { - let result = unsafe { (*state_ptr).fetch_data(id_captured).await }; - - // For remote/local handlers - let resp = Response::new() - .body(serde_json::to_vec(&result).unwrap()); - resp.send().unwrap(); - } -} -``` - -The `hyper!` macro lets our custom runtime execute this async code. - #### WIT Bindings Generation We parse the `wit_world` in our `/api` folder with: @@ -1334,8 +1432,8 @@ wit_bindgen::generate!({ world: #wit_world, generate_unused_types: true, additional_derives: [ - serde::Deserialize, - serde::Serialize, + serde::Deserialize, + serde::Serialize, process_macros::SerdeJsonInto ], }); @@ -1366,7 +1464,7 @@ impl Guest for Component { // Setup server with endpoints let mut server = setup_server(ui_config.as_ref(), &endpoints); - + // Call user's init method if provided if #init_method_ident.is_some() { #init_method_call @@ -1402,19 +1500,19 @@ graph TB classDef external fill:#222222,color:#ffffff,stroke:#444444,stroke-width:1px classDef dataflow fill:#008CBA,color:#ffffff,stroke:#0077A3,stroke-width:1px classDef annotation fill:none,color:#FF6600,stroke:none,stroke-width:0px - + %% BUILD PHASE - Where components are generated subgraph BuildPhase["⚙️ BUILD PHASE"] UserSrc[/"User Source Code #[hyperprocess] macro #[http], #[local], #[remote] methods"/] - + subgraph CodeGen["Code Generation Pipeline"] direction TB - + HyperBindgen["hyper-bindgen CLI Scans for #[hyperprocess]"] - + subgraph BindgenOutputs["hyper-bindgen Outputs"] direction LR WitFiles["WIT Files @@ -1424,98 +1522,98 @@ graph TB EnumStructs["Shared Enums & Structs Cross-process types"] end - + ProcMacro["hyperprocess Macro AST Transformation"] - + subgraph MacroOutputs["Macro Generated Code"] direction LR ReqResEnums["Request/Response Enums - Generated variants per handler - Parameter & return mappings"] - + HandlerDisp["Handler Dispatch Logic - HTTP/Local/Remote routing - Async handler spawning - Message serialization"] - + AsyncRuntime["Async Runtime Components - ResponseFuture impl - Correlation ID system - Executor & task management"] - + MainLoop["Component Implementation - Message loop - Task polling - Error handling"] end end - + %% Dev-time Connections UserSrc --> HyperBindgen UserSrc --> ProcMacro HyperBindgen --> BindgenOutputs ProcMacro --> MacroOutputs - + %% Final Compilation MacroOutputs --> WasmComp["WebAssembly Component WASI Preview 2"] BindgenOutputs --> WasmComp end - + %% RUNTIME PHASE - How processes execute subgraph RuntimePhase["⚡ RUNTIME PHASE"] subgraph Process["Process A"] direction TB - + InMsg[/"Incoming Messages"/] --> MsgLoop["Message Loop await_message()"] - + subgraph ProcessInternals["Process Internals"] direction LR - + MsgLoop --> MsgRouter{"Message Router"} MsgRouter -->|"HTTP"| HttpHandler["HTTP Handlers"] MsgRouter -->|"Local"| LocalHandler["Local Handlers"] MsgRouter -->|"Remote"| RemoteHandler["Remote Handlers"] MsgRouter -->|"WebSocket"| WsHandler["WebSocket Handlers"] MsgRouter -->|"Response"| RespHandler["Response Handler"] - + %% State management HttpHandler & LocalHandler & RemoteHandler & WsHandler --> AppState[("Application State SaveOptions::EveryMessage")] - + %% Async handling RespHandler --> RespRegistry["Response Registry correlation_id → response"] - + CallStub["RPC Stub Calls e.g. increment_counter_rpc()"] end - + %% Asynchronous execution AppState -.->|"Persist"| Storage[(Persistent Storage)] - + MsgLoop -.->|"Poll Tasks"| Executor["Async Executor poll_all_tasks()"] - + ProcessInternals -->|"Generate"| OutMsg[/"Outgoing Messages"/] end - + %% External communication points ExtClient1["HTTP Client"] & ExtClient2["WebSocket Client"] --> InMsg OutMsg --> Process2["Process B"] Process2 --> InMsg end - + %% ASYNC FLOW - Detailed sequence of async communication subgraph AsyncFlow["⚡ ASYNC MESSAGE EXCHANGE"] direction LR - + AF1["1️⃣ Call RPC Stub - increment_counter_rpc(target, 42)"] --> + increment_counter_rpc(target, 42)"] --> AF2["2️⃣ Generate UUID - correlation_id = uuid::new_v4()"] --> + correlation_id = uuid::new_v4()"] --> AF3["3️⃣ Create Future ResponseFuture(correlation_id)"] --> AF4["4️⃣ Send Request @@ -1531,21 +1629,21 @@ graph TB AF9["9️⃣ Future Polling ResponseFuture finds response and completes"] end - + %% KEY CONNECTIONS BETWEEN SECTIONS - + %% Build to Runtime WasmComp ==>|"Load Component"| Process - + %% Runtime to Async Flow CallStub ==>|"Initiates"| AF1 AF9 ==>|"Resume Future in"| Executor RespRegistry ===|"Powers"| AF8 - + %% Annotation for the Correlation ID system CorrelationNote["CORRELATION SYSTEM Tracks request→response with UUIDs"] -.-> RespRegistry - + %% Style elements class UserSrc,WitFiles,CallerUtils,EnumStructs,ReqResEnums,HandlerDisp,AsyncRuntime,MainLoop,WasmComp mainflow class MsgLoop,Executor,RespRegistry,RespHandler,AF2,AF8 accent @@ -1553,7 +1651,7 @@ graph TB class AF1,AF3,AF4,AF5,AF6,AF7,AF9 asyncflow class ExtClient1,ExtClient2,Process2,Storage,InMsg,OutMsg external class CorrelationNote annotation - + %% Subgraph styling style BuildPhase fill:#171717,stroke:#333333,color:#ffffff style CodeGen fill:#222222,stroke:#444444,color:#ffffff @@ -1568,4 +1666,4 @@ graph TB ## Todos -- Let the new kit templates make use of the new framework \ No newline at end of file +- Let the new kit templates make use of the new framework diff --git a/hyperprocess_macro/Cargo.toml b/hyperprocess_macro/Cargo.toml deleted file mode 100644 index 6a86d77..0000000 --- a/hyperprocess_macro/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "hyperprocess_macro" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "2.0", features = ["full", "extra-traits"] } - -anyhow = "1.0" -futures-util = "0.3" -hyperware_app_common = { path = "../hyperware_app_common" } -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", features = ["logging"], rev = "cfd6843" } -once_cell = "1.20.2" -paste = "1.0" -process_macros = "0.1.0" -rmp-serde = "1.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -serde_derive = "1.0" -uuid = { version = "1.0", features = ["v4"] } -wit-bindgen = "0.36.0" diff --git a/hyperware_app_common/Cargo.toml b/hyperware_app_common/Cargo.toml deleted file mode 100644 index ecaaa8c..0000000 --- a/hyperware_app_common/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "hyperware_app_common" -version = "0.1.0" -edition = "2021" -publish = false - -[dependencies] -anyhow = "1.0" -hyperware_process_lib = { git = "https://github.com/hyperware-ai/process_lib", features = ["logging"], rev = "cfd6843" } -futures-util = "0.3" -once_cell = "1.20.2" -paste = "1.0" -process_macros = "0.1.0" -serde = { version = "1.0", features = ["derive"] } -rmp-serde = "1.1.2" -serde_json = "1.0" -serde_derive = "1.0" -thiserror = "2" -uuid = { version = "1.0", features = ["v4"] } -wit-bindgen = "0.36.0" - -[lib] -crate-type = ["lib"] - diff --git a/hyperware_app_common/src/lib.rs b/hyperware_app_common/src/lib.rs deleted file mode 100644 index 0af91ef..0000000 --- a/hyperware_app_common/src/lib.rs +++ /dev/null @@ -1,542 +0,0 @@ -// this is hyperware_app_common -use std::cell::RefCell; -use std::collections::HashMap; -use std::future::Future; -use std::pin::Pin; -use std::task::{Context, Poll}; - -use futures_util::task::noop_waker_ref; -use hyperware_process_lib::{ - http::server::{HttpServer, IncomingHttpRequest}, - logging::info, - get_state, http, set_state, timer, BuildError, LazyLoadBlob, Message, Request, SendError, -}; -use serde::{Deserialize, Serialize}; -use thiserror::Error; -use uuid::Uuid; - -pub use hyperware_process_lib; - -pub mod prelude { - pub use crate::APP_CONTEXT; - pub use crate::RESPONSE_REGISTRY; - // Add other commonly used items here -} - -thread_local! { - pub static APP_CONTEXT: RefCell = RefCell::new(AppContext { - hidden_state: None, - executor: Executor::new(), - }); - - pub static RESPONSE_REGISTRY: RefCell>> = RefCell::new(HashMap::new()); - - pub static APP_HELPERS: RefCell = RefCell::new(AppHelpers { - current_server: None, - current_message: None, - current_http_context: None, - }); -} - -#[derive(Clone)] -pub struct HttpRequestContext { - pub request: IncomingHttpRequest, - pub response_headers: HashMap, -} - -pub struct AppContext { - pub hidden_state: Option, - pub executor: Executor, -} - -pub struct AppHelpers { - pub current_server: Option<*mut HttpServer>, - pub current_message: Option, - pub current_http_context: Option, -} - -// Access function for the current path -pub fn get_path() -> Option { - APP_HELPERS.with(|helpers| { - helpers.borrow().current_http_context.as_ref() - .and_then(|ctx| ctx.request.path().ok()) - }) -} - -// Access function for the current server -pub fn get_server() -> Option<&'static mut HttpServer> { - APP_HELPERS.with(|ctx| ctx.borrow().current_server.map(|ptr| unsafe { &mut *ptr })) -} - -pub fn get_http_method() -> Option { - APP_HELPERS.with(|helpers| { - helpers.borrow().current_http_context.as_ref() - .and_then(|ctx| ctx.request.method().ok()) - .map(|m| m.to_string()) - }) -} - -// Set response headers that will be included in the HTTP response -pub fn set_response_headers(headers: HashMap) { - APP_HELPERS.with(|helpers| { - if let Some(ctx) = &mut helpers.borrow_mut().current_http_context { - ctx.response_headers = headers; - } - }) -} - -// Add a single response header -pub fn add_response_header(key: String, value: String) { - APP_HELPERS.with(|helpers| { - if let Some(ctx) = &mut helpers.borrow_mut().current_http_context { - ctx.response_headers.insert(key, value); - } - }) -} - - -pub fn clear_http_request_context() { - APP_HELPERS.with(|helpers| { - helpers.borrow_mut().current_http_context = None; - }) -} - -// Access function for the source address of the current message -pub fn source() -> hyperware_process_lib::Address { - APP_HELPERS.with(|ctx| { - ctx.borrow() - .current_message - .as_ref() - .expect("No message in current context") - .source() - .clone() - }) -} - -/// Get query parameters from the current HTTP request path -/// Returns None if not in an HTTP context or no query parameters present -pub fn get_query_params() -> Option> { - get_path().map(|path| { - let mut params = HashMap::new(); - if let Some(query_start) = path.find('?') { - let query = &path[query_start + 1..]; - for pair in query.split('&') { - if let Some(eq_pos) = pair.find('=') { - let key = pair[..eq_pos].to_string(); - let value = pair[eq_pos + 1..].to_string(); - params.insert(key, value); - } - } - } - params - }) -} - -pub struct Executor { - tasks: Vec>>>, -} - -impl Executor { - pub fn new() -> Self { - Self { tasks: Vec::new() } - } - - pub fn spawn(&mut self, fut: impl Future + 'static) { - self.tasks.push(Box::pin(fut)); - } - - pub fn poll_all_tasks(&mut self) { - let mut ctx = Context::from_waker(noop_waker_ref()); - let mut completed = Vec::new(); - - for i in 0..self.tasks.len() { - if let Poll::Ready(()) = self.tasks[i].as_mut().poll(&mut ctx) { - completed.push(i); - } - } - - for idx in completed.into_iter().rev() { - let _ = self.tasks.remove(idx); - } - } -} -struct ResponseFuture { - correlation_id: String, - // Capture HTTP context at creation time - http_context: Option, -} - -impl ResponseFuture { - fn new(correlation_id: String) -> Self { - // Capture current HTTP context when future is created (at .await point) - let http_context = APP_HELPERS.with(|helpers| { - helpers.borrow().current_http_context.clone() - }); - - Self { - correlation_id, - http_context, - } - } -} - -impl Future for ResponseFuture { - type Output = Vec; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let correlation_id = &self.correlation_id; - - let maybe_bytes = RESPONSE_REGISTRY.with(|registry| { - let mut registry_mut = registry.borrow_mut(); - registry_mut.remove(correlation_id) - }); - - if let Some(bytes) = maybe_bytes { - // Restore this future's captured context - if let Some(ref context) = self.http_context { - APP_HELPERS.with(|helpers| { - helpers.borrow_mut().current_http_context = Some(context.clone()); - }); - } - - Poll::Ready(bytes) - } else { - Poll::Pending - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize, Error)] -pub enum AppSendError { - #[error("SendError: {0}")] - SendError(SendError), - #[error("BuildError: {0}")] - BuildError(BuildError), -} - -pub async fn sleep(sleep_ms: u64) -> Result<(), AppSendError> { - let request = Request::to(("our", "timer", "distro", "sys")) - .body(timer::TimerAction::SetTimer(sleep_ms)) - .expects_response((sleep_ms / 1_000) + 1); - - let correlation_id = Uuid::new_v4().to_string(); - if let Err(e) = request.context(correlation_id.as_bytes().to_vec()).send() { - return Err(AppSendError::BuildError(e)); - } - - let _ = ResponseFuture::new(correlation_id).await; - - return Ok(()); -} - -pub async fn send(request: Request) -> Result -where - R: serde::de::DeserializeOwned, -{ - let request = if request.timeout.is_some() { - request - } else { - request.expects_response(30) - }; - - let correlation_id = Uuid::new_v4().to_string(); - if let Err(e) = request.context(correlation_id.as_bytes().to_vec()).send() { - return Err(AppSendError::BuildError(e)); - } - - let response_bytes = ResponseFuture::new(correlation_id).await; - if let Ok(r) = serde_json::from_slice::(&response_bytes) { - return Ok(r); - } - - let e = serde_json::from_slice::(&response_bytes) - .expect("Failed to deserialize response to send()"); - return Err(AppSendError::SendError(e)); -} - -pub async fn send_rmp(request: Request) -> Result -where - R: serde::de::DeserializeOwned, -{ - let request = if request.timeout.is_some() { - request - } else { - request.expects_response(30) - }; - - let correlation_id = Uuid::new_v4().to_string(); - if let Err(e) = request.context(correlation_id.as_bytes().to_vec()).send() { - return Err(AppSendError::BuildError(e)); - } - - let response_bytes = ResponseFuture::new(correlation_id).await; - if let Ok(r) = rmp_serde::from_slice::(&response_bytes) { - return Ok(r); - } - - let e = rmp_serde::from_slice::(&response_bytes) - .expect("Failed to deserialize response to send()"); - return Err(AppSendError::SendError(e)); -} - -#[macro_export] -macro_rules! hyper { - ($($code:tt)*) => { - $crate::APP_CONTEXT.with(|ctx| { - ctx.borrow_mut().executor.spawn(async move { - $($code)* - }) - }) - }; -} - - -// Enum defining the state persistance behaviour -#[derive(Clone)] -pub enum SaveOptions { - // Never Persist State - Never, - // Persist State Every Message - EveryMessage, - // Persist State Every N Messages - EveryNMessage(u64), - // Persist State Every N Seconds - EveryNSeconds(u64), - // Persist State Only If Changed - OnDiff, -} -pub struct HiddenState { - save_config: SaveOptions, - message_count: u64, - old_state: Option>, // Stores the serialized state from before message processing -} - -impl HiddenState { - pub fn new(save_config: SaveOptions) -> Self { - Self { - save_config, - message_count: 0, - old_state: None, - } - } - - fn should_save_state(&mut self) -> bool { - match self.save_config { - SaveOptions::Never => false, - SaveOptions::EveryMessage => true, - SaveOptions::EveryNMessage(n) => { - self.message_count += 1; - if self.message_count >= n { - self.message_count = 0; - true - } else { - false - } - } - SaveOptions::EveryNSeconds(_) => false, // Handled by timer instead - SaveOptions::OnDiff => false, // Will be handled separately with state comparison - } - } -} - -// TODO: We need a timer macro again. - -/// Store a snapshot of the current state before processing a message -/// This is used for OnDiff save option to compare state before and after -/// Only stores if old_state is None (i.e., first time or after a save) -pub fn store_old_state(state: &S) -where - S: serde::Serialize, -{ - APP_CONTEXT.with(|ctx| { - let mut ctx_mut = ctx.borrow_mut(); - if let Some(ref mut hidden_state) = ctx_mut.hidden_state { - if matches!(hidden_state.save_config, SaveOptions::OnDiff) && hidden_state.old_state.is_none() { - if let Ok(s_bytes) = rmp_serde::to_vec(state) { - hidden_state.old_state = Some(s_bytes); - } - } - } - }); -} - -/// Trait that must be implemented by application state types -pub trait State { - /// Creates a new instance of the state. - fn new() -> Self; -} - -/// Initialize state from persisted storage or create new if none exists -/// TODO: Delete? -pub fn initialize_state() -> S -where - S: serde::de::DeserializeOwned + Default, -{ - match get_state() { - Some(bytes) => match rmp_serde::from_slice::(&bytes) { - Ok(state) => state, - Err(e) => { - panic!("error deserializing existing state: {e}. We're panicking because we don't want to nuke state by setting it to a new instance."); - } - }, - None => { - info!("no existing state, creating new one"); - S::default() - } - } -} - -pub fn setup_server( - ui_config: Option<&hyperware_process_lib::http::server::HttpBindingConfig>, - endpoints: &[Binding], -) -> http::server::HttpServer { - let mut server = http::server::HttpServer::new(5); - - if let Some(ui) = ui_config { - if let Err(e) = server.serve_ui("ui", vec!["/"], ui.clone()) { - panic!("failed to serve UI: {e}. Make sure that a ui folder is in /pkg"); - } - } - - // Verify no duplicate paths - let mut seen_paths = std::collections::HashSet::new(); - for endpoint in endpoints.iter() { - let path = match endpoint { - Binding::Http { path, .. } => path, - Binding::Ws { path, .. } => path, - }; - if !seen_paths.insert(path) { - panic!("duplicate path found: {}", path); - } - } - - for endpoint in endpoints { - match endpoint { - Binding::Http { path, config } => { - server - .bind_http_path(path.to_string(), config.clone()) - .expect("failed to serve API path"); - } - Binding::Ws { path, config } => { - server - .bind_ws_path(path.to_string(), config.clone()) - .expect("failed to bind WS path"); - } - } - } - - server -} - -/// Pretty prints a SendError in a more readable format -pub fn pretty_print_send_error(error: &SendError) { - let kind = &error.kind; - let target = &error.target; - - // Try to decode body as UTF-8 string, fall back to showing as bytes - let body = String::from_utf8(error.message.body().to_vec()) - .map(|s| format!("\"{}\"", s)) - .unwrap_or_else(|_| format!("{:?}", error.message.body())); - - // Try to decode context as UTF-8 string - let context = error - .context - .as_ref() - .map(|bytes| String::from_utf8_lossy(bytes).into_owned()); - - hyperware_process_lib::logging::error!( - "SendError {{ - kind: {:?}, - target: {}, - body: {}, - context: {} -}}", - kind, - target, - body, - context - .map(|s| format!("\"{}\"", s)) - .unwrap_or("None".to_string()) - ); -} - -// For demonstration, we'll define them all in one place. -// Make sure the signatures match the real function signatures you require! -pub fn no_init_fn(_state: &mut S) { - // does nothing -} - -pub fn no_ws_handler( - _state: &mut S, - _server: &mut http::server::HttpServer, - _channel_id: u32, - _msg_type: http::server::WsMessageType, - _blob: LazyLoadBlob, -) { - // does nothing -} - -pub fn no_http_api_call(_state: &mut S, _req: ()) { - // does nothing -} - -pub fn no_local_request(_msg: &Message, _state: &mut S, _req: ()) { - // does nothing -} - -pub fn no_remote_request(_msg: &Message, _state: &mut S, _req: ()) { - // does nothing -} - -#[derive(Clone, Debug)] -pub enum Binding { - Http { - path: &'static str, - config: hyperware_process_lib::http::server::HttpBindingConfig, - }, - Ws { - path: &'static str, - config: hyperware_process_lib::http::server::WsBindingConfig, - }, -} - -pub fn maybe_save_state(state: &S) -where - S: serde::Serialize, -{ - APP_CONTEXT.with(|ctx| { - let mut ctx_mut = ctx.borrow_mut(); - if let Some(ref mut hidden_state) = ctx_mut.hidden_state { - let should_save = if matches!(hidden_state.save_config, SaveOptions::OnDiff) { - // For OnDiff, compare current state with old state - if let Ok(current_bytes) = rmp_serde::to_vec(state) { - let state_changed = match &hidden_state.old_state { - Some(old_bytes) => old_bytes != ¤t_bytes, - None => true, // If no old state, consider it changed - }; - - if state_changed { - true - } else { - false - } - } else { - false - } - } else { - hidden_state.should_save_state() - }; - - if should_save { - if let Ok(s_bytes) = rmp_serde::to_vec(state) { - let _ = set_state(&s_bytes); - - // Clear old_state after saving so it can be set again on next message - if matches!(hidden_state.save_config, SaveOptions::OnDiff) { - hidden_state.old_state = None; - } - } - } - } - }); -} diff --git a/metadata.json b/metadata.json deleted file mode 100644 index 54fd1aa..0000000 --- a/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "async-app", - "description": "", - "image": "", - "properties": { - "package_name": "async-app", - "current_version": "0.1.0", - "publisher": "uncentered.os", - "mirrors": [], - "code_hashes": { - "0.1.0": "" - }, - "wit_version": 1, - "dependencies": [] - }, - "external_url": "", - "animation_url": "" -} diff --git a/pkg/manifest.json b/pkg/manifest.json deleted file mode 100644 index e69de29..0000000 diff --git a/hyperprocess_macro/src/lib.rs b/src/lib.rs similarity index 69% rename from hyperprocess_macro/src/lib.rs rename to src/lib.rs index f79c917..41235b3 100644 --- a/hyperprocess_macro/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ mod kw { syn::custom_keyword!(icon); syn::custom_keyword!(widget); syn::custom_keyword!(ui); + syn::custom_keyword!(ui_path); syn::custom_keyword!(endpoints); syn::custom_keyword!(save_config); syn::custom_keyword!(wit_world); @@ -30,6 +31,7 @@ struct HyperProcessArgs { icon: Option, widget: Option, ui: Option, + ui_path: Option, endpoints: Expr, save_config: Expr, wit_world: String, @@ -46,6 +48,7 @@ struct FunctionMetadata { is_local: bool, // Has #[local] attribute is_remote: bool, // Has #[remote] attribute is_http: bool, // Has #[http] attribute + is_eth: bool, // Has #[eth] attribute http_methods: Vec, // HTTP methods this handler accepts (GET, POST, etc.) http_path: Option, // Specific path this handler is bound to (optional) } @@ -56,6 +59,7 @@ enum HandlerType { Local, Remote, Http, + Eth, } /// Grouped handlers by type @@ -114,12 +118,45 @@ struct InitMethodDetails { call: proc_macro2::TokenStream, } +/// WebSocket method info from analysis +#[derive(Clone)] +struct WsMethodInfo { + name: syn::Ident, + is_async: bool, +} + +/// WebSocket client method info from analysis +#[derive(Clone)] +struct WsClientMethodInfo { + name: syn::Ident, + is_async: bool, +} + +/// ETH method info from analysis +#[derive(Clone)] +struct EthMethodInfo { + name: syn::Ident, + is_async: bool, +} + /// WebSocket method details for code generation struct WsMethodDetails { identifier: proc_macro2::TokenStream, call: proc_macro2::TokenStream, } +/// WebSocket client method details for code generation +struct WsClientMethodDetails { + identifier: proc_macro2::TokenStream, + call: proc_macro2::TokenStream, +} + +/// ETH method details for code generation +struct EthMethodDetails { + identifier: proc_macro2::TokenStream, + call: proc_macro2::TokenStream, +} + //------------------------------------------------------------------------------ // Parse Implementation //------------------------------------------------------------------------------ @@ -333,7 +370,9 @@ fn clean_impl_block(impl_block: &ItemImpl) -> ItemImpl { && !attr.path().is_ident("http") && !attr.path().is_ident("local") && !attr.path().is_ident("remote") + && !attr.path().is_ident("eth") && !attr.path().is_ident("ws") + && !attr.path().is_ident("ws_client") }); } } @@ -359,6 +398,7 @@ fn parse_args(attr_args: MetaList) -> syn::Result { let mut icon = None; let mut widget = None; let mut ui = None; + let mut ui_path = None; let mut endpoints = None; let mut save_config = None; let mut wit_world = None; @@ -384,6 +424,9 @@ fn parse_args(attr_args: MetaList) -> syn::Result { "ui" => { ui = parse_ui_expr(&nv.value)?; } + "ui_path" => { + ui_path = Some(parse_string_literal(&nv.value, nv.value.span())?); + } "endpoints" => endpoints = Some(nv.value.clone()), "save_config" => save_config = Some(nv.value.clone()), "wit_world" => { @@ -401,6 +444,7 @@ fn parse_args(attr_args: MetaList) -> syn::Result { icon, widget, ui, + ui_path, endpoints: endpoints.ok_or_else(|| syn::Error::new(span, "Missing 'endpoints'"))?, save_config: save_config.ok_or_else(|| syn::Error::new(span, "Missing 'save_config'"))?, wit_world: wit_world.ok_or_else(|| syn::Error::new(span, "Missing 'wit_world'"))?, @@ -518,6 +562,76 @@ fn validate_websocket_method(method: &syn::ImplItemFn) -> syn::Result<()> { Ok(()) } +/// Validate the websocket client method signature +fn validate_websocket_client_method(method: &syn::ImplItemFn) -> syn::Result<()> { + // Ensure first param is &mut self + if !has_valid_self_receiver(method) { + return Err(syn::Error::new_spanned( + &method.sig, + "WebSocket client method must take &mut self as first parameter", + )); + } + + // Ensure there are exactly 4 parameters (including &mut self) + if method.sig.inputs.len() != 4 { + return Err(syn::Error::new_spanned( + &method.sig, + "WebSocket client method must take exactly 3 additional parameters: channel_id, message_type, and blob", + )); + } + + // Get parameters (excluding &mut self) + let params: Vec<_> = method.sig.inputs.iter().skip(1).collect(); + + // Check parameter types (we're not doing exact type checking, just rough check) + let channel_id_param = ¶ms[0]; + let message_type_param = ¶ms[1]; + let blob_param = ¶ms[2]; + + if let syn::FnArg::Typed(pat_type) = channel_id_param { + if !pat_type.ty.to_token_stream().to_string().contains("u32") { + return Err(syn::Error::new_spanned( + pat_type, + "First parameter of WebSocket client method must be channel_id: u32", + )); + } + } + + if let syn::FnArg::Typed(pat_type) = message_type_param { + let type_str = pat_type.ty.to_token_stream().to_string(); + if !type_str.contains("WsMessageType") && !type_str.contains("MessageType") { + return Err(syn::Error::new_spanned( + pat_type, + "Second parameter of WebSocket client method must be message_type: WsMessageType", + )); + } + } + + if let syn::FnArg::Typed(pat_type) = blob_param { + if !pat_type + .ty + .to_token_stream() + .to_string() + .contains("LazyLoadBlob") + { + return Err(syn::Error::new_spanned( + pat_type, + "Third parameter of WebSocket client method must be blob: LazyLoadBlob", + )); + } + } + + // Validate return type (must be unit) + if !matches!(method.sig.output, ReturnType::Default) { + return Err(syn::Error::new_spanned( + &method.sig.output, + "WebSocket client method must not return a value", + )); + } + + Ok(()) +} + /// Validate a request-response function signature fn validate_request_response_function(method: &syn::ImplItemFn) -> syn::Result<()> { // Ensure first param is &mut self @@ -534,6 +648,47 @@ fn validate_request_response_function(method: &syn::ImplItemFn) -> syn::Result<( Ok(()) } +/// Validate the ETH handler signature +fn validate_eth_handler(method: &syn::ImplItemFn) -> syn::Result<()> { + // Ensure first param is &mut self + if !has_valid_self_receiver(method) { + return Err(syn::Error::new_spanned( + &method.sig, + "ETH handler must take &mut self as first parameter", + )); + } + + // Ensure there are exactly 2 parameters (&mut self + eth_sub_result) + if method.sig.inputs.len() != 2 { + return Err(syn::Error::new_spanned( + &method.sig, + "ETH handler must take exactly one parameter: eth_sub_result: EthSubResult", + )); + } + + // Get the second parameter (the eth_sub_result parameter) + let params: Vec<_> = method.sig.inputs.iter().skip(1).collect(); + let eth_param = ¶ms[0]; + + if let syn::FnArg::Typed(pat_type) = eth_param { + let type_str = pat_type.ty.to_token_stream().to_string(); + if !type_str.contains("EthSubResult") { + return Err(syn::Error::new_spanned( + pat_type, + "ETH handler parameter must be eth_sub_result: EthSubResult", + )); + } + } else { + return Err(syn::Error::new_spanned( + eth_param, + "ETH handler parameter must be eth_sub_result: EthSubResult", + )); + } + + // Any return type is allowed + Ok(()) +} + //------------------------------------------------------------------------------ // Method Analysis Functions //------------------------------------------------------------------------------ @@ -542,13 +697,17 @@ fn validate_request_response_function(method: &syn::ImplItemFn) -> syn::Result<( fn analyze_methods( impl_block: &ItemImpl, ) -> syn::Result<( - Option, // init method - Option, // ws method - Vec, // metadata for request/response methods - bool, // whether init method contains logging init + Option, // init method + Option, // ws method + Option, // ws_client method + Option, // eth method + Vec, // metadata for request/response methods + bool, // whether init method contains logging init )> { let mut init_method = None; let mut ws_method = None; + let mut ws_client_method = None; + let mut eth_method = None; let mut has_init_logging = false; let mut function_metadata = Vec::new(); @@ -561,11 +720,13 @@ fn analyze_methods( let has_http = has_attribute(method, "http"); let has_local = has_attribute(method, "local"); let has_remote = has_attribute(method, "remote"); + let has_eth = has_attribute(method, "eth"); let has_ws = has_attribute(method, "ws"); + let has_ws_client = has_attribute(method, "ws_client"); // Handle init method if has_init { - if has_http || has_local || has_remote || has_ws { + if has_http || has_local || has_remote || has_eth || has_ws || has_ws_client { return Err(syn::Error::new_spanned( method, "#[init] cannot be combined with other attributes", @@ -588,7 +749,7 @@ fn analyze_methods( // Handle WebSocket method if has_ws { - if has_http || has_local || has_remote || has_init { + if has_http || has_local || has_remote || has_eth || has_init || has_ws_client { return Err(syn::Error::new_spanned( method, "#[ws] cannot be combined with other attributes", @@ -601,14 +762,62 @@ fn analyze_methods( "Multiple #[ws] methods defined", )); } - ws_method = Some(ident); + ws_method = Some(WsMethodInfo { + name: ident, + is_async: method.sig.asyncness.is_some(), + }); + continue; + } + + // Handle WebSocket client method + if has_ws_client { + if has_http || has_local || has_remote || has_eth || has_init || has_ws { + return Err(syn::Error::new_spanned( + method, + "#[ws_client] cannot be combined with other attributes", + )); + } + validate_websocket_client_method(method)?; + if ws_client_method.is_some() { + return Err(syn::Error::new_spanned( + method, + "Multiple #[ws_client] methods defined", + )); + } + ws_client_method = Some(WsClientMethodInfo { + name: ident, + is_async: method.sig.asyncness.is_some(), + }); continue; } - // Handle request-response methods + // Handle ETH method + if has_eth { + if has_http || has_local || has_remote || has_init || has_ws || has_ws_client { + return Err(syn::Error::new_spanned( + method, + "#[eth] cannot be combined with other attributes", + )); + } + validate_eth_handler(method)?; + if eth_method.is_some() { + return Err(syn::Error::new_spanned( + method, + "Multiple #[eth] methods defined", + )); + } + eth_method = Some(EthMethodInfo { + name: ident.clone(), + is_async: method.sig.asyncness.is_some(), + }); + // Continue with regular processing for function metadata + } + + // Handle request-response methods (local, remote, http - NOT eth) if has_http || has_local || has_remote { validate_request_response_function(method)?; - let metadata = extract_function_metadata(method, has_local, has_remote, has_http); + let metadata = + extract_function_metadata(method, has_local, has_remote, has_http, false); // Parameter-less HTTP handlers can optionally specify a path, but it's not required // They can use get_path() and get_method() to handle requests dynamically @@ -622,7 +831,7 @@ fn analyze_methods( if function_metadata.is_empty() { return Err(syn::Error::new( proc_macro2::Span::call_site(), - "You must specify at least one handler with #[remote], #[local], or #[http] attribute. Without any handlers, this hyperprocess wouldn't respond to any requests.", + "You must specify at least one handler with #[remote], #[local] or #[http] attribute. Without any handlers, this hyperprocess wouldn't respond to any requests.", )); } @@ -660,7 +869,14 @@ fn analyze_methods( } } - Ok((init_method, ws_method, function_metadata, has_init_logging)) + Ok(( + init_method, + ws_method, + ws_client_method, + eth_method, + function_metadata, + has_init_logging, + )) } /// Extract metadata from a function @@ -669,6 +885,7 @@ fn extract_function_metadata( is_local: bool, is_remote: bool, is_http: bool, + is_eth: bool, ) -> FunctionMetadata { let ident = method.sig.ident.clone(); @@ -712,6 +929,7 @@ fn extract_function_metadata( is_local, is_remote, is_http, + is_eth, http_methods, http_path, } @@ -842,6 +1060,7 @@ fn generate_handler_dispatch( HandlerType::Local => "No local handlers defined but received a local request", HandlerType::Remote => "No remote handlers defined but received a remote request", HandlerType::Http => "No HTTP handlers defined but received an HTTP request", + HandlerType::Eth => "No ETH handlers defined but received an ETH request", }; return quote! { hyperware_process_lib::logging::warn!(#message); @@ -852,15 +1071,82 @@ fn generate_handler_dispatch( HandlerType::Local => "local", HandlerType::Remote => "remote", HandlerType::Http => "http", + HandlerType::Eth => "eth", }; let dispatch_arms = handlers .iter() .map(|func| generate_handler_dispatch_arm(func, self_ty, handler_type, type_name)); - // Add an explicit unreachable for other variants - let unreachable_arm = quote! { - _ => unreachable!(concat!("Non-", #type_name, " request variant received in ", #type_name, " handler")) + // Gracefully handle unexpected variants + let unreachable_arm = match handler_type { + HandlerType::Http => { + quote! { + unexpected => { + hyperware_process_lib::logging::error!( + "Unexpected {} request variant received in HTTP handler: {:?}", + #type_name, + unexpected + ); + + let error_body = serde_json::json!({ + "error": format!("Unexpected {} request variant", #type_name), + "received": format!("{:?}", unexpected), + }) + .to_string() + .into_bytes(); + + hyperware_process_lib::http::server::send_response( + hyperware_process_lib::http::StatusCode::BAD_REQUEST, + None, + error_body, + ); + + hyperware_process_lib::hyperapp::clear_http_request_context(); + } + } + } + _ => { + quote! { + unexpected => { + hyperware_process_lib::logging::error!( + "Unexpected {} request variant received in {} handler: {:?}", + #type_name, + #type_name, + unexpected + ); + + let send_error_bytes = hyperware_process_lib::hyperapp::APP_HELPERS.with(|helpers| { + let helpers_ref = helpers.borrow(); + helpers_ref.current_message.clone().map(|original_message| { + let send_error = hyperware_process_lib::SendError { + kind: hyperware_process_lib::SendErrorKind::Timeout, + target: original_message.source().clone(), + message: original_message, + lazy_load_blob: None, + context: None, + }; + serde_json::to_vec(&send_error) + }) + }); + + if let Some(Ok(payload_bytes)) = send_error_bytes { + if let Err(e) = hyperware_process_lib::Response::new().body(payload_bytes).send() { + hyperware_process_lib::logging::error!( + "Failed to send SendError for unexpected {} variant: {}", + #type_name, + e + ); + } + } else { + hyperware_process_lib::logging::error!( + "Failed to construct a SendError for unexpected {} variant", + #type_name, + ); + } + } + } + } }; quote! { @@ -908,13 +1194,21 @@ fn generate_response_handling( resp.send().unwrap(); } } + HandlerType::Eth => { + quote! { + // Instead of wrapping in HPMResponse enum, directly serialize the result + let resp = hyperware_process_lib::Response::new() + .body(serde_json::to_vec(&result).unwrap()); + resp.send().unwrap(); + } + } HandlerType::Http => { quote! { // Instead of wrapping in HPMResponse enum, directly serialize the result let response_bytes = serde_json::to_vec(&result).unwrap(); // Get headers from the current HTTP context - let headers_opt = hyperware_app_common::APP_HELPERS.with(|helpers| { + let headers_opt = hyperware_process_lib::hyperapp::APP_HELPERS.with(|helpers| { helpers.borrow().current_http_context.as_ref().and_then(|ctx| { if ctx.response_headers.is_empty() { None @@ -924,14 +1218,24 @@ fn generate_response_handling( }) }); + // Get status code from the current HTTP context + let response_status = hyperware_process_lib::hyperapp::APP_HELPERS.with(|helpers| { + helpers + .borrow() + .current_http_context + .as_ref() + .map(|ctx| ctx.response_status) + .unwrap_or(hyperware_process_lib::http::StatusCode::OK) + }); + hyperware_process_lib::http::server::send_response( - hyperware_process_lib::http::StatusCode::OK, + response_status, headers_opt, response_bytes ); // Clear HTTP context immediately after sending the response - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); } } } @@ -951,11 +1255,11 @@ fn generate_async_handler_arm( HPMRequest::#variant_name{} => { // Create a raw pointer to state for use in the async block let state_ptr: *mut #self_ty = state; - hyperware_app_common::hyper! { + hyperware_process_lib::hyperapp::spawn(async move { // Inside the async block, use the pointer to access state let result = unsafe { (*state_ptr).#fn_name().await }; #response_handling - } + }); } } } else if func.params.len() == 1 { @@ -965,11 +1269,11 @@ fn generate_async_handler_arm( let param_captured = param; // Capture param before moving into async block // Create a raw pointer to state for use in the async block let state_ptr: *mut #self_ty = state; - hyperware_app_common::hyper! { + hyperware_process_lib::hyperapp::spawn(async move { // Inside the async block, use the pointer to access state let result = unsafe { (*state_ptr).#fn_name(param_captured).await }; #response_handling - } + }); } } } else { @@ -989,11 +1293,11 @@ fn generate_async_handler_arm( #(#capture_statements)* // Create a raw pointer to state for use in the async block let state_ptr: *mut #self_ty = state; - hyperware_app_common::hyper! { + hyperware_process_lib::hyperapp::spawn(async move { // Inside the async block, use the pointer to access state let result = unsafe { (*state_ptr).#fn_name(#(#captured_names),*).await }; #response_handling - } + }); } } } @@ -1057,10 +1361,10 @@ fn init_method_opt_to_call( quote! { // Create a pointer to state for use in the async block let state_ptr: *mut #self_ty = &mut state; - hyperware_app_common::hyper! { + hyperware_process_lib::hyperapp::spawn(async move { // Inside the async block, use the pointer to access state unsafe { (*state_ptr).#method_name().await }; - } + }); } } else { quote! {} @@ -1068,8 +1372,9 @@ fn init_method_opt_to_call( } /// Convert optional WebSocket method to token stream for identifier -fn ws_method_opt_to_token(ws_method: &Option) -> proc_macro2::TokenStream { - if let Some(method_name) = ws_method { +fn ws_method_opt_to_token(ws_method: &Option) -> proc_macro2::TokenStream { + if let Some(method_info) = ws_method { + let method_name = &method_info.name; quote! { Some(stringify!(#method_name)) } } else { quote! { None::<&str> } @@ -1077,9 +1382,94 @@ fn ws_method_opt_to_token(ws_method: &Option) -> proc_macro2::TokenS } /// Convert optional WebSocket method to token stream for method call -fn ws_method_opt_to_call(ws_method: &Option) -> proc_macro2::TokenStream { - if let Some(method_name) = ws_method { - quote! { unsafe { (*state).#method_name(channel_id, message_type, blob) }; } +fn ws_method_opt_to_call( + ws_method: &Option, + self_ty: &Box, +) -> proc_macro2::TokenStream { + if let Some(method_info) = ws_method { + let method_name = &method_info.name; + if method_info.is_async { + quote! { + // Create a raw pointer to state for use in the async block + let state_ptr: *mut #self_ty = state; + hyperware_process_lib::hyperapp::spawn(async move { + // Inside the async block, use the pointer to access state + unsafe { (*state_ptr).#method_name(channel_id, message_type, blob).await }; + }); + } + } else { + quote! { unsafe { (*state).#method_name(channel_id, message_type, blob) }; } + } + } else { + quote! {} + } +} + +/// Convert optional WebSocket client method to token stream for identifier +fn ws_client_method_opt_to_token( + ws_client_method: &Option, +) -> proc_macro2::TokenStream { + if let Some(method_info) = ws_client_method { + let method_name = &method_info.name; + quote! { Some(stringify!(#method_name)) } + } else { + quote! { None::<&str> } + } +} + +/// Convert optional WebSocket client method to token stream for method call +fn ws_client_method_opt_to_call( + ws_client_method: &Option, + self_ty: &Box, +) -> proc_macro2::TokenStream { + if let Some(method_info) = ws_client_method { + let method_name = &method_info.name; + if method_info.is_async { + quote! { + // Create a raw pointer to state for use in the async block + let state_ptr: *mut #self_ty = state; + hyperware_process_lib::hyperapp::spawn(async move { + // Inside the async block, use the pointer to access state + unsafe { (*state_ptr).#method_name(channel_id, message_type, blob).await }; + }); + } + } else { + quote! { unsafe { (*state).#method_name(channel_id, message_type, blob) }; } + } + } else { + quote! {} + } +} + +/// Convert optional ETH method to token stream for identifier +fn eth_method_opt_to_token(eth_method: &Option) -> proc_macro2::TokenStream { + if let Some(method_info) = eth_method { + let method_name = &method_info.name; + quote! { Some(stringify!(#method_name)) } + } else { + quote! { None::<&str> } + } +} + +/// Convert optional ETH method to token stream for method call +fn eth_method_opt_to_call( + eth_method: &Option, + self_ty: &Box, +) -> proc_macro2::TokenStream { + if let Some(method_info) = eth_method { + let method_name = &method_info.name; + if method_info.is_async { + quote! { + // Create a raw pointer to state for use in the async block + let state_ptr: *mut #self_ty = state; + hyperware_process_lib::hyperapp::spawn(async move { + // Inside the async block, use the pointer to access state + unsafe { (*state_ptr).#method_name(eth_sub_result).await }; + }); + } + } else { + quote! { unsafe { (*state).#method_name(eth_sub_result) }; } + } } else { quote! {} } @@ -1092,10 +1482,11 @@ fn ws_method_opt_to_call(ws_method: &Option) -> proc_macro2::TokenSt /// Generate HTTP context setup code fn generate_http_context_setup() -> proc_macro2::TokenStream { quote! { - hyperware_app_common::APP_HELPERS.with(|helpers| { - helpers.borrow_mut().current_http_context = Some(hyperware_app_common::HttpRequestContext { + hyperware_process_lib::hyperapp::APP_HELPERS.with(|helpers| { + helpers.borrow_mut().current_http_context = Some(hyperware_process_lib::hyperapp::HttpRequestContext { request: http_request, response_headers: std::collections::HashMap::new(), + response_status: hyperware_process_lib::http::StatusCode::OK, }); }); hyperware_process_lib::logging::debug!("HTTP context established"); @@ -1105,7 +1496,7 @@ fn generate_http_context_setup() -> proc_macro2::TokenStream { /// Generate HTTP context cleanup code fn generate_http_context_cleanup() -> proc_macro2::TokenStream { quote! { - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); } } @@ -1129,13 +1520,13 @@ fn generate_http_error_response( /// Generate HTTP method and path parsing code fn generate_http_request_parsing() -> proc_macro2::TokenStream { quote! { - let http_method = hyperware_app_common::get_http_method() + let http_method = hyperware_process_lib::hyperapp::get_http_method() .unwrap_or_else(|| { hyperware_process_lib::logging::warn!("Failed to get HTTP method from request context"); "UNKNOWN".to_string() }); - let current_path = match hyperware_app_common::get_path() { + let current_path = match hyperware_process_lib::hyperapp::get_path() { Some(path) => { hyperware_process_lib::logging::debug!("Successfully parsed HTTP path: '{}'", path); path @@ -1147,7 +1538,7 @@ fn generate_http_request_parsing() -> proc_macro2::TokenStream { None, b"Invalid path: no HTTP context available".to_vec(), ); - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); return; } }; @@ -1189,7 +1580,7 @@ fn generate_parameterized_handler_dispatch( HPMRequest::#variant_name(..) => { unsafe { #http_request_match_arms - hyperware_app_common::maybe_save_state(&mut *state); + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } }, _ => { @@ -1224,7 +1615,7 @@ fn generate_parameterized_handler_dispatch( None, error_details.into_bytes() ); - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); return; } } @@ -1277,7 +1668,7 @@ fn generate_parameterless_handler_dispatch( } }; - let headers_opt = hyperware_app_common::APP_HELPERS.with(|helpers| { + let headers_opt = hyperware_process_lib::hyperapp::APP_HELPERS.with(|helpers| { helpers.borrow().current_http_context.as_ref().and_then(|ctx| { if ctx.response_headers.is_empty() { None @@ -1287,29 +1678,38 @@ fn generate_parameterless_handler_dispatch( }) }); + let response_status = hyperware_process_lib::hyperapp::APP_HELPERS.with(|helpers| { + helpers + .borrow() + .current_http_context + .as_ref() + .map(|ctx| ctx.response_status) + .unwrap_or(hyperware_process_lib::http::StatusCode::OK) + }); + hyperware_process_lib::http::server::send_response( - hyperware_process_lib::http::StatusCode::OK, + response_status, headers_opt, response_bytes ); - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); }; let handler_body = if handler.is_async { quote! { let state_ptr: *mut #self_ty = state; - hyperware_app_common::hyper! { + hyperware_process_lib::hyperapp::spawn(async move { let result = unsafe { (*state_ptr).#fn_name().await }; #response_handling - } - unsafe { hyperware_app_common::maybe_save_state(&mut *state); } + }); + unsafe { hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } } } else { quote! { let result = unsafe { (*state).#fn_name() }; #response_handling - unsafe { hyperware_app_common::maybe_save_state(&mut *state); } + unsafe { hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } } }; @@ -1370,7 +1770,7 @@ fn generate_http_handler_dispatcher( hyperware_process_lib::logging::debug!("Successfully parsed request body, dispatching to specific handler"); unsafe { #http_request_match_arms - hyperware_app_common::maybe_save_state(&mut *state); + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } return; }, @@ -1396,7 +1796,7 @@ fn generate_http_handler_dispatcher( None, error_details.into_bytes() ); - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); return; } } @@ -1412,7 +1812,7 @@ fn generate_http_handler_dispatcher( None, format!("No handler found for {} {}", http_method, current_path).into_bytes(), ); - hyperware_app_common::clear_http_request_context(); + hyperware_process_lib::hyperapp::clear_http_request_context(); } } @@ -1420,6 +1820,77 @@ fn generate_http_handler_dispatcher( // WebSocket Helper Functions //------------------------------------------------------------------------------ +/// Generate WebSocket client message handler +fn generate_websocket_client_handler( + ws_client_method_call: &proc_macro2::TokenStream, + self_ty: &Box, +) -> proc_macro2::TokenStream { + quote! { + let blob_opt = message.blob(); + + match serde_json::from_slice::(message.body()) { + Ok(request) => { + match request { + hyperware_process_lib::http::client::HttpClientRequest::WebSocketPush { channel_id, message_type } => { + hyperware_process_lib::logging::debug!("Received WebSocket client push on channel {}, type: {:?}", channel_id, message_type); + + if message_type == hyperware_process_lib::http::server::WsMessageType::Pong { + return; + } + + if message_type == hyperware_process_lib::http::server::WsMessageType::Ping { + // Respond to Pings with Pongs + hyperware_process_lib::http::client::send_ws_client_push( + channel_id, + hyperware_process_lib::http::server::WsMessageType::Pong, + hyperware_process_lib::LazyLoadBlob::default(), + ); + return; + } + + let Some(blob) = blob_opt else { + hyperware_process_lib::logging::error!( + "Failed to get blob for WebSocket client push on channel {}. This indicates a malformed WebSocket message.", + channel_id + ); + return; + }; + + hyperware_process_lib::logging::debug!("Processing WebSocket client message with {} bytes", blob.bytes.len()); + + #ws_client_method_call + + unsafe { + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); + } + }, + hyperware_process_lib::http::client::HttpClientRequest::WebSocketClose { channel_id } => { + hyperware_process_lib::logging::debug!("WebSocket client connection closed on channel {}", channel_id); + + // Call the handler with a special Close message type and empty blob + let message_type = hyperware_process_lib::http::server::WsMessageType::Close; + let blob = hyperware_process_lib::LazyLoadBlob::default(); + + #ws_client_method_call + + unsafe { + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); + } + } + } + }, + Err(e) => { + hyperware_process_lib::logging::error!( + "Failed to parse WebSocket client request: {}\n\ + Source: {:?}\n\ + This usually indicates a malformed message from the http-client service.", + e, message.source() + ); + } + } + } +} + /// Generate WebSocket message handler fn generate_websocket_handler( ws_method_call: &proc_macro2::TokenStream, @@ -1429,6 +1900,20 @@ fn generate_websocket_handler( hyperware_process_lib::http::server::HttpServerRequest::WebSocketPush { channel_id, message_type } => { hyperware_process_lib::logging::debug!("Received WebSocket message on channel {}, type: {:?}", channel_id, message_type); + if message_type == hyperware_process_lib::http::server::WsMessageType::Pong { + return; + } + + if message_type == hyperware_process_lib::http::server::WsMessageType::Ping { + // Respond to Pings with Pongs + hyperware_process_lib::http::server::send_ws_push( + channel_id, + hyperware_process_lib::http::server::WsMessageType::Pong, + hyperware_process_lib::LazyLoadBlob::default(), + ); + return; + } + let Some(blob) = blob_opt else { hyperware_process_lib::logging::error!( "Failed to get blob for WebSocketPush on channel {}. This indicates a malformed WebSocket message.", @@ -1441,19 +1926,19 @@ fn generate_websocket_handler( #ws_method_call unsafe { - hyperware_app_common::maybe_save_state(&mut *state); + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } }, hyperware_process_lib::http::server::HttpServerRequest::WebSocketOpen { path, channel_id } => { hyperware_process_lib::logging::debug!("WebSocket connection opened on path '{}' with channel {}", path, channel_id); - match hyperware_app_common::get_server() { + match hyperware_process_lib::hyperapp::get_server() { Some(server) => server.handle_websocket_open(&path, channel_id), None => hyperware_process_lib::logging::error!("Failed to get server instance for WebSocket open event") } }, hyperware_process_lib::http::server::HttpServerRequest::WebSocketClose(channel_id) => { hyperware_process_lib::logging::debug!("WebSocket connection closed on channel {}", channel_id); - match hyperware_app_common::get_server() { + match hyperware_process_lib::hyperapp::get_server() { Some(server) => server.handle_websocket_close(channel_id), None => hyperware_process_lib::logging::error!("Failed to get server instance for WebSocket close event") } @@ -1478,7 +1963,7 @@ fn generate_local_message_handler( Ok(request) => { unsafe { #match_arms - hyperware_app_common::maybe_save_state(&mut *state); + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } }, Err(e) => { @@ -1489,7 +1974,8 @@ fn generate_local_message_handler( Source: {:?}\n\ Body: {}\n\ \n\ - 💡 This usually means the message format doesn't match any of your #[local] or #[remote] handlers.", + 💡 This usually means the message format doesn't match any of your #[local] or #[remote] handlers.\n\ + 💡 If you are sending an HTTP message, if it is malformed, it might have ended up in the local message handler.", e, message.source(), raw_body ); } @@ -1511,7 +1997,7 @@ fn generate_remote_message_handler( Ok(request) => { unsafe { #match_arms - hyperware_app_common::maybe_save_state(&mut *state); + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } }, Err(e) => { @@ -1536,6 +2022,8 @@ fn generate_message_handlers( self_ty: &Box, handler_arms: &HandlerDispatch, ws_method_call: &proc_macro2::TokenStream, + ws_client_method_call: &proc_macro2::TokenStream, + eth_method_call: &proc_macro2::TokenStream, http_handlers: &[&FunctionMetadata], ) -> proc_macro2::TokenStream { let http_request_match_arms = &handler_arms.http; @@ -1547,44 +2035,74 @@ fn generate_message_handlers( let http_dispatcher = generate_http_handler_dispatcher(http_handlers, self_ty, http_request_match_arms); let websocket_handlers = generate_websocket_handler(ws_method_call, self_ty); + let websocket_client_handler = + generate_websocket_client_handler(ws_client_method_call, self_ty); let local_message_handler = generate_local_message_handler(self_ty, local_and_remote_request_match_arms); let remote_message_handler = generate_remote_message_handler(self_ty, remote_request_match_arms); + let eth_message_handler = generate_eth_message_handler(self_ty, eth_method_call); quote! { + /// Handle WebSocket client messages + fn handle_websocket_client_message(state: *mut #self_ty, message: hyperware_process_lib::Message) { + #websocket_client_handler + } /// Handle messages from the HTTP server - fn handle_http_server_message(state: *mut #self_ty, message: hyperware_process_lib::Message) { - let blob_opt = message.blob(); - - match serde_json::from_slice::(message.body()) { - Ok(http_server_request) => { - match http_server_request { - hyperware_process_lib::http::server::HttpServerRequest::Http(http_request) => { - hyperware_process_lib::logging::debug!("Processing HTTP request, message has blob: {}", blob_opt.is_some()); - if let Some(ref blob) = blob_opt { - hyperware_process_lib::logging::debug!("Blob size: {} bytes, content: {}", blob.bytes.len(), String::from_utf8_lossy(&blob.bytes[..std::cmp::min(200, blob.bytes.len())])); - } + fn handle_http_server_message(state: *mut #self_ty, http_server_request: hyperware_process_lib::http::server::HttpServerRequest, blob_opt: Option) { + match http_server_request { + hyperware_process_lib::http::server::HttpServerRequest::Http(http_request) => { + hyperware_process_lib::logging::debug!("Processing HTTP request, message has blob: {}", blob_opt.is_some()); + if let Some(ref blob) = blob_opt { + hyperware_process_lib::logging::debug!("Blob size: {} bytes, content: {}", blob.bytes.len(), String::from_utf8_lossy(&blob.bytes[..std::cmp::min(200, blob.bytes.len())])); + } + #http_context_setup + #http_request_parsing + #http_dispatcher + }, + #websocket_handlers + } + } + + #local_message_handler + #remote_message_handler + #eth_message_handler + } +} - #http_context_setup - #http_request_parsing - #http_dispatcher - }, - #websocket_handlers +/// Generate ETH message handler +fn generate_eth_message_handler( + self_ty: &Box, + eth_method_call: &proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + quote! { + /// Handle ETH messages + fn handle_eth_message(state: *mut #self_ty, message: hyperware_process_lib::Message) { + hyperware_process_lib::logging::debug!("Processing ETH message from: {:?}", message.source()); + + // ETH messages contain EthSubResult directly, not wrapped in HPMRequest + match serde_json::from_slice::(message.body()) { + Ok(eth_sub_result) => { + hyperware_process_lib::logging::debug!("Successfully parsed EthSubResult, calling ETH handler"); + #eth_method_call + unsafe { + hyperware_process_lib::hyperapp::maybe_save_state(&mut *state); } }, Err(e) => { + let raw_body = String::from_utf8_lossy(message.body()); hyperware_process_lib::logging::error!( - "Failed to parse HTTP server request: {}\n\ - This usually indicates a malformed message to the HTTP server.", - e + "Failed to deserialize ETH message into EthSubResult.\n\ + Error: {}\n\ + Source: {:?}\n\ + Body: {}\n\ + \n\ + 💡 This usually means the message format from eth:distro:sys doesn't match EthSubResult.", + e, message.source(), raw_body ); } } } - - #local_message_handler - #remote_message_handler } } @@ -1607,6 +2125,8 @@ fn generate_component_impl( response_enum: &proc_macro2::TokenStream, init_method_details: &InitMethodDetails, ws_method_details: &WsMethodDetails, + ws_client_method_details: &WsClientMethodDetails, + eth_method_details: &EthMethodDetails, handler_arms: &HandlerDispatch, has_init_logging: bool, http_handlers: &[&FunctionMetadata], @@ -1638,13 +2158,26 @@ fn generate_component_impl( None => quote! { None }, }; + let ui_path = match &args.ui_path { + Some(path_str) => quote! { Some(#path_str.to_string()) }, + None => quote! { None }, + }; + let init_method_ident = &init_method_details.identifier; let init_method_call = &init_method_details.call; let ws_method_call = &ws_method_details.call; + let ws_client_method_call = &ws_client_method_details.call; + let eth_method_call = ð_method_details.call; // Generate message handler functions - let message_handlers = - generate_message_handlers(self_ty, handler_arms, ws_method_call, http_handlers); + let message_handlers = generate_message_handlers( + self_ty, + handler_arms, + ws_method_call, + ws_client_method_call, + eth_method_call, + http_handlers, + ); // Generate the logging initialization conditionally let logging_init = if !has_init_logging { @@ -1669,10 +2202,9 @@ fn generate_component_impl( additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], }); - use hyperware_app_common::hyperware_process_lib as hyperware_process_lib; use hyperware_process_lib::http::server::HttpBindingConfig; use hyperware_process_lib::http::server::WsBindingConfig; - use hyperware_app_common::Binding; + use hyperware_process_lib::hyperapp::Binding; #cleaned_impl_block @@ -1686,12 +2218,12 @@ fn generate_component_impl( impl Guest for Component { fn init(_our: String) { // Initialize our state - let mut state = hyperware_app_common::initialize_state::<#self_ty>(); + let mut state = hyperware_process_lib::hyperapp::initialize_state::<#self_ty>(); // Set to persist state according to user setting - hyperware_app_common::APP_CONTEXT.with(|ctx| { + hyperware_process_lib::hyperapp::APP_CONTEXT.with(|ctx| { ctx.borrow_mut().hidden_state = Some( - hyperware_app_common::HiddenState::new(#save_config) + hyperware_process_lib::hyperapp::HiddenState::new(#save_config) ); }); @@ -1700,6 +2232,7 @@ fn generate_component_impl( let app_icon = #icon; let app_widget = #widget; let ui_config = #ui; + let ui_path = #ui_path; let endpoints = #endpoints; // Setup UI if needed @@ -1710,8 +2243,8 @@ fn generate_component_impl( #logging_init // Setup server with endpoints - let mut server = hyperware_app_common::setup_server(ui_config.as_ref(), &endpoints); - hyperware_app_common::APP_HELPERS.with(|ctx| { + let mut server = hyperware_process_lib::hyperapp::setup_server(ui_config.as_ref(), ui_path, &endpoints); + hyperware_process_lib::hyperapp::APP_HELPERS.with(|ctx| { ctx.borrow_mut().current_server = Some(&mut server); }); @@ -1722,19 +2255,19 @@ fn generate_component_impl( // Main event loop loop { - hyperware_app_common::APP_CONTEXT.with(|ctx| { + hyperware_process_lib::hyperapp::APP_CONTEXT.with(|ctx| { ctx.borrow_mut().executor.poll_all_tasks(); }); match hyperware_process_lib::await_message() { Ok(message) => { - hyperware_app_common::APP_HELPERS.with(|ctx| { + hyperware_process_lib::hyperapp::APP_HELPERS.with(|ctx| { ctx.borrow_mut().current_message = Some(message.clone()); }); // Store old state if needed (for OnDiff save option) // This only stores if old_state is None (first time or after a save) - hyperware_app_common::store_old_state(&state); + hyperware_process_lib::hyperapp::store_old_state(&state); match message { hyperware_process_lib::Message::Response { body, context, .. } => { @@ -1742,15 +2275,27 @@ fn generate_component_impl( .as_deref() .map(|bytes| String::from_utf8_lossy(bytes).to_string()) .unwrap_or_else(|| "no context".to_string()); - - hyperware_app_common::RESPONSE_REGISTRY.with(|registry| { - let mut registry_mut = registry.borrow_mut(); - registry_mut.insert(correlation_id, body); - }); + let was_cancelled = + hyperware_process_lib::hyperapp::CANCELLED_RESPONSES.with(|set| { + set.borrow_mut().remove(&correlation_id) + }); + if !was_cancelled { + hyperware_process_lib::hyperapp::RESPONSE_REGISTRY.with(|registry| { + registry.borrow_mut().insert(correlation_id, body); + }); + } } hyperware_process_lib::Message::Request { .. } => { if message.is_local() && message.source().process == "http-server:distro:sys" { - handle_http_server_message(&mut state, message); + if let Ok(http_server_request) = serde_json::from_slice::(message.body()) { + handle_http_server_message(&mut state, http_server_request, message.blob()); + } else { + handle_local_message(&mut state, message); + } + } else if message.is_local() && message.source().process == "http-client:distro:sys" { + handle_websocket_client_message(&mut state, message); + } else if message.is_local() && message.source().process == "eth:distro:sys" { + handle_eth_message(&mut state, message); } else if message.is_local() { handle_local_message(&mut state, message); } else { @@ -1767,13 +2312,19 @@ fn generate_component_impl( { let correlation_id = String::from_utf8_lossy(context) .to_string(); - - hyperware_app_common::RESPONSE_REGISTRY.with(|registry| { - let mut registry_mut = registry.borrow_mut(); - registry_mut.insert(correlation_id, serde_json::to_vec(error).unwrap()); - }); + let was_cancelled = + hyperware_process_lib::hyperapp::CANCELLED_RESPONSES.with(|set| { + set.borrow_mut().remove(&correlation_id) + }); + if !was_cancelled { + hyperware_process_lib::hyperapp::RESPONSE_REGISTRY.with(|registry| { + registry.borrow_mut().insert( + correlation_id, + serde_json::to_vec(error).unwrap(), + ); + }); + } } - } } } @@ -1805,7 +2356,7 @@ pub fn hyperprocess(attr: TokenStream, item: TokenStream) -> TokenStream { let self_ty = &impl_block.self_ty; // Analyze the methods in the implementation block - let (init_method, ws_method, function_metadata, has_init_logging) = + let (init_method, ws_method, ws_client_method, eth_method, function_metadata, has_init_logging) = match analyze_methods(&impl_block) { Ok(methods) => methods, Err(e) => return e.to_compile_error().into(), @@ -1815,20 +2366,11 @@ pub fn hyperprocess(attr: TokenStream, item: TokenStream) -> TokenStream { let handlers = HandlerGroups::from_function_metadata(&function_metadata); // HTTP handlers with parameters will be part of the HPMRequest enum and dispatched via body deserialization. - let http_handlers_with_params: Vec<_> = handlers - .http - .iter() - //.filter(|h| !h.params.is_empty()) - .cloned() - .collect(); + let http_handlers_with_params: Vec<_> = handlers.http.iter().cloned().collect(); // Collect all function metadata that will be represented in the HPMRequest enum. // This includes all local and remote handlers, plus HTTP handlers that have parameters. - let metadata_for_enum: Vec<_> = function_metadata - .iter() - //.filter(|f| !f.is_http || !f.params.is_empty()) - .cloned() - .collect(); + let metadata_for_enum: Vec<_> = function_metadata.iter().cloned().collect(); // Generate HPMRequest and HPMResponse enums from the filtered list of functions let (request_enum, response_enum) = generate_request_response_enums(&metadata_for_enum); @@ -1859,7 +2401,19 @@ pub fn hyperprocess(attr: TokenStream, item: TokenStream) -> TokenStream { // Prepare WebSocket method details for code generation let ws_method_details = WsMethodDetails { identifier: ws_method_opt_to_token(&ws_method), - call: ws_method_opt_to_call(&ws_method), + call: ws_method_opt_to_call(&ws_method, self_ty), + }; + + // Prepare WebSocket client method details for code generation + let ws_client_method_details = WsClientMethodDetails { + identifier: ws_client_method_opt_to_token(&ws_client_method), + call: ws_client_method_opt_to_call(&ws_client_method, self_ty), + }; + + // Prepare ETH method details for code generation + let eth_method_details = EthMethodDetails { + identifier: eth_method_opt_to_token(ð_method), + call: eth_method_opt_to_call(ð_method, self_ty), }; // Generate the final output @@ -1871,6 +2425,8 @@ pub fn hyperprocess(attr: TokenStream, item: TokenStream) -> TokenStream { &response_enum, &init_method_details, &ws_method_details, + &ws_client_method_details, + ð_method_details, &handler_arms, has_init_logging, &handlers.http,