From 5eb9492e6cbc8ee19140a4bc2e00f2bad85a3d06 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Thu, 10 Oct 2024 15:21:38 -0400 Subject: [PATCH 01/13] contacts system prim --- Cargo.lock | 10 + Cargo.toml | 1 + kinode/packages/contacts/Cargo.lock | 3174 ++++++++++++++++++ kinode/packages/contacts/Cargo.toml | 10 + kinode/packages/contacts/contacts/Cargo.toml | 19 + kinode/packages/contacts/contacts/src/icon | 1 + kinode/packages/contacts/contacts/src/lib.rs | 291 ++ kinode/packages/contacts/metadata.json | 18 + kinode/packages/contacts/pkg/manifest.json | 18 + kinode/packages/contacts/pkg/ui/index.html | 235 ++ kinode/packages/contacts/pkg/ui/script.js | 320 ++ 11 files changed, 4097 insertions(+) create mode 100644 kinode/packages/contacts/Cargo.lock create mode 100644 kinode/packages/contacts/Cargo.toml create mode 100644 kinode/packages/contacts/contacts/Cargo.toml create mode 100644 kinode/packages/contacts/contacts/src/icon create mode 100644 kinode/packages/contacts/contacts/src/lib.rs create mode 100644 kinode/packages/contacts/metadata.json create mode 100644 kinode/packages/contacts/pkg/manifest.json create mode 100644 kinode/packages/contacts/pkg/ui/index.html create mode 100644 kinode/packages/contacts/pkg/ui/script.js diff --git a/Cargo.lock b/Cargo.lock index 7c154408..7913eca2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1849,6 +1849,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "contacts" +version = "0.1.0" +dependencies = [ + "kinode_process_lib 0.9.1", + "serde", + "serde_json", + "wit-bindgen", +] + [[package]] name = "convert_case" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 8e405dd6..c1413943 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ members = [ "kinode/packages/app_store/app_store", "kinode/packages/app_store/ft_worker", "kinode/packages/app_store/download", "kinode/packages/app_store/install", "kinode/packages/app_store/uninstall", "kinode/packages/app_store/downloads", "kinode/packages/app_store/chain", "kinode/packages/chess/chess", + "kinode/packages/contacts/contacts", "kinode/packages/homepage/homepage", "kinode/packages/kino_updates/blog", "kinode/packages/kino_updates/globe", "kinode/packages/kns_indexer/kns_indexer", "kinode/packages/kns_indexer/get_block", "kinode/packages/kns_indexer/state", diff --git a/kinode/packages/contacts/Cargo.lock b/kinode/packages/contacts/Cargo.lock new file mode 100644 index 00000000..ad63c9ae --- /dev/null +++ b/kinode/packages/contacts/Cargo.lock @@ -0,0 +1,3174 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "alloy" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ba1c79677c9ce51c8d45e20845b05e6fb070ea2c863fba03ad6af2c778474bd" +dependencies = [ + "alloy-consensus", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-json-rpc", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-transport-http", +] + +[[package]] +name = "alloy-chains" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c225801d42099570d0674701dddd4142f0ef715282aeb5985042e2ec962df7" +dependencies = [ + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da374e868f54c7f4ad2ad56829827badca388efd645f8cf5fccc61c2b5343504" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "serde", +] + +[[package]] +name = "alloy-core" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529fc6310dc1126c8de51c376cbc59c79c7f662bd742be7dc67055d5421a81b4" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow", +] + +[[package]] +name = "alloy-eips" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f76ecab54890cdea1e4808fc0891c7e6cfcf71fe1a9fe26810c7280ef768f4ed" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "once_cell", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca15afde1b6d15e3fc1c97421262b1bbb37aee45752e3c8b6d6f13f776554ff" +dependencies = [ + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d6f34930b7e3e2744bcc79056c217f00cb2abb33bc5d4ff88da7623c5bb078b" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f6895fc31b48fa12306ef9b4f78b7764f8bd6d7d91cdb0a40e233704a0f23f" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "thiserror", +] + +[[package]] +name = "alloy-primitives" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c538bfa893d07e27cb4f3c1ab5f451592b7c526d511d62b576a2ce59e146e4a" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "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", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26154390b1d205a4a7ac7352aa2eb4f81f391399d4e2f546fb81a2f8bb383f62" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d0f2d905ebd295e7effec65e5f6868d153936130ae718352771de3e7d03c75c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba31bae67773fd5a60020bea900231f8396202b7feca4d0c70c6b59308ab4a8" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "184a7a42c7ba9141cc9e76368356168c282c3bc3d9e5d78f3556bdfe39343447" +dependencies = [ + "alloy-rpc-types-eth", + "alloy-serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4123ee21f99ba4bd31bfa36ba89112a18a500f8b452f02b35708b1b951e2b9" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.13.0", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9416c52959e66ead795a11f4a86c248410e9e368a0765710e57055b8a1774dd6" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33753c09fa1ad85e5b092b8dc2372f1e337a42e84b9b4cff9fede75ba4adb32" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.79", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e482dc33a32b6fadbc0f599adea520bd3aaa585c141a80b404d0a3e3fa72528" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.79", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" +dependencies = [ + "serde", + "winnow", +] + +[[package]] +name = "alloy-sol-types" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" +dependencies = [ + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b51a291f949f755e6165c3ed562883175c97423703703355f4faa4b7d0a57c" +dependencies = [ + "alloy-json-rpc", + "base64", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-transport-http" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d65871f9f1cafe1ed25cde2f1303be83e6473e995a2d56c275ae4fcce6119c" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[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-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[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.79", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[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.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +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.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-hex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "contacts" +version = "0.1.0" +dependencies = [ + "kinode_process_lib", + "serde", + "serde_json", + "wit-bindgen", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.79", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dunce" +version = "1.0.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 = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "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.79", +] + +[[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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb94a0ffd3f3ee755c20f7d8752f45cac88605a4dcf808abcff72873296ec7b" +dependencies = [ + "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-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 = "kinode_process_lib" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7722aef4bff0625445fafda89a02f82ce0e16c7def6024e1317ae55a632ad331" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "bincode", + "http", + "mime_guess", + "rand", + "rmp-serde", + "serde", + "serde_json", + "thiserror", + "url", + "wit-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.0", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +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.79", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pin-project" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[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.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + +[[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.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.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.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3-asm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spdx" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +dependencies = [ + "smallvec", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.79", +] + +[[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.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c837dc8852cb7074e46b444afb81783140dab12c58867b49fb3898fbafedf7ea" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[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.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[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.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef073ced962d62984fb38a36e5fdc1a2b23c9e0e1fa0689bb97afa4202ef6887" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4bfab14ef75323f4eb75fa52ee0a3fb59611977fd3240da19b2cf36ff85030e" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65471f79c1022ffa5291d33520cbbb53b7687b01c2f8e83b57d102eed7ed479d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7bec9830f60924d9ceb3ef99d55c155be8afa76954edffbb5936ff4509474e7" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c74f6e152a76a2ad448e223b0fc0b6b5747649c3d769cc6bf45737bf97d0ed6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42f6c679374623f295a8623adfe63d9284091245c3504bde47c17a3ce2777d9" + +[[package]] +name = "wasm-encoder" +version = "0.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd106365a7f5f7aa3c1916a98cbb3ad477f5ff96ddb130285a91c6e7429e67a" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-metadata" +version = "0.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094aea3cb90e09f16ee25a4c0e324b3e8c934e7fd838bfa039aef5352f44a917" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6998515d3cf3f8b980ef7c11b29a9b1017d4cf86b99ae93b546992df9931413" +dependencies = [ + "bitflags", + "indexmap", + "semver 1.0.23", +] + +[[package]] +name = "web-sys" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44188d185b5bdcae1052d08bcbcf9091a5524038d4572cc4f4f2bb9d5554ddd9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "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.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb4e7653763780be47e38f479e9aa83c768aa6a3b2ed086dc2826fdbbb7e7f5" +dependencies = [ + "wit-bindgen-rt", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b67e11c950041849a10828c7600ea62a4077c01e8af72e8593253575428f91b" +dependencies = [ + "anyhow", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0780cf7046630ed70f689a098cd8d56c5c3b22f2a7379bbdb088879963ff96" +dependencies = [ + "bitflags", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30acbe8fb708c3a830a33c4cb705df82659bf831b492ec6ca1a17a369cfeeafb" +dependencies = [ + "anyhow", + "heck 0.4.1", + "indexmap", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b1b06eae85feaecdf9f2854f7cac124e00d5a6e5014bfb02eb1ecdeb5f265b9" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.79", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c836b1fd9932de0431c1758d8be08212071b6bba0151f7bac826dbc4312a2a9" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.202.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744237b488352f4f27bca05a10acb79474415951c450e52ebd0da784c1df2bcc" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver 1.0.23", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] diff --git a/kinode/packages/contacts/Cargo.toml b/kinode/packages/contacts/Cargo.toml new file mode 100644 index 00000000..43e1d296 --- /dev/null +++ b/kinode/packages/contacts/Cargo.toml @@ -0,0 +1,10 @@ +[workspace] +resolver = "2" +members = [ + "contacts", +] + +[profile.release] +panic = "abort" +opt-level = "s" +lto = true diff --git a/kinode/packages/contacts/contacts/Cargo.toml b/kinode/packages/contacts/contacts/Cargo.toml new file mode 100644 index 00000000..c8704114 --- /dev/null +++ b/kinode/packages/contacts/contacts/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "contacts" +version = "0.1.0" +edition = "2021" + +[features] +simulation-mode = [] + +[dependencies] +kinode_process_lib = "0.9.1" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +wit-bindgen = "0.24.0" + +[lib] +crate-type = ["cdylib"] + +[package.metadata.component] +package = "kinode:process" diff --git a/kinode/packages/contacts/contacts/src/icon b/kinode/packages/contacts/contacts/src/icon new file mode 100644 index 00000000..d5143fe3 --- /dev/null +++ b/kinode/packages/contacts/contacts/src/icon @@ -0,0 +1 @@ +data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM2IiBoZWlnaHQ9IjEzNiIgdmlld0JveD0iMCAwIDEzNiAxMzYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMzYiIGhlaWdodD0iMTM2IiByeD0iNjgiIGZpbGw9IiNGRkY1RDkiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xODIxXzkwOTMpIj4KPHBhdGggZD0iTTY3LjQ4NTUgOTQuOTg4MUM2NS44MTYxIDk0Ljk4ODEgNjQuMTQ2NyA5NC45NjQzIDYyLjQ3NzIgOTQuOTg4MUM2MS41NjAyIDk1LjAxMTkgNjEuMDQyOSA5NC40MTc0IDYwLjkzNzEgOTMuNjQ0N0M2MC42NjY3IDkxLjU1MjMgNjAuMzQ5MyA4OS40NTk4IDYwLjA2NzEgODcuMzY3NEM2MC4wMjAxIDg3LjAxMDggNTkuODc5IDg2Ljc5NjggNTkuNTM4MSA4Ni42NTQxQzU4LjIzMzEgODYuMDgzNCA1Ny4wMjIyIDg1LjM1ODIgNTUuODgxOCA4NC40OTA0QzU1LjYyMzEgODQuMjg4MiA1NS4zOTk4IDg0LjI2NDUgNTUuMDk0MSA4NC4zOTUyQzUzLjE1NDMgODUuMjAzNyA1MS4yMTQ0IDg1Ljk4ODMgNDkuMjc0NiA4Ni43NzNDNDguMjc1MyA4Ny4xNzcyIDQ3Ljc5MzMgODcuMDIyNyA0Ny4yNTI1IDg2LjA5NTNDNDUuNTcxMyA4My4xNTg4IDQzLjg5MDEgODAuMjEwNCA0Mi4yMDg5IDc3LjI2MkM0MS44MDkyIDc2LjU3MjUgNDEuOTI2NyA3NS45NDIzIDQyLjU0OTggNzUuNDQzQzQ0LjIzMSA3NC4wOTk2IDQ1LjkxMjIgNzIuNzU2MiA0Ny42MDUyIDcxLjQzNjVDNDcuODk5MSA3MS4yMTA2IDQ4LjAwNDkgNzAuOTYxIDQ3Ljk1NzkgNzAuNTkyNEM0Ny43ODE1IDY5LjIwMTQgNDcuNzkzMyA2Ny43OTg2IDQ3Ljk1NzkgNjYuNDA3NkM0OC4wMDQ5IDY2LjA1MDkgNDcuOTEwOCA2NS44MTMxIDQ3LjYyODcgNjUuNTg3M0M0NS45OTQ1IDY0LjMwMzMgNDQuMzYwNCA2My4wMDc0IDQyLjczNzkgNjEuNzExNUM0MS44Nzk3IDYxLjAzMzkgNDEuNzczOSA2MC41MTA4IDQyLjMxNDcgNTkuNTcxNkM0NC4wMDc3IDU2LjYxMTMgNDUuNjg4OCA1My42MzkxIDQ3LjM5MzYgNTAuNjc4OEM0Ny43NDYyIDUwLjA3MjUgNDguMzgxMSA0OS44NTg1IDQ5LjA3NDcgNTAuMTQzOEM1MC40MjY3IDUwLjY5MDcgNTEuNzc4OCA1MS4yMzc1IDUzLjEzMDggNTEuNzk2M0M1My44MjQ0IDUyLjA4MTcgNTQuNTE4IDUyLjM1NTEgNTUuMjExNyA1Mi42NTIzQzU1LjQyMzMgNTIuNzQ3NCA1NS41ODc5IDUyLjczNTUgNTUuNzc2IDUyLjU5MjlDNTYuOTg2OSA1MS42NjU1IDU4LjMwMzYgNTAuODkyOCA1OS43MDI3IDUwLjI4NjVDNTkuOTQ5NiA1MC4xNzk1IDYwLjAyMDEgNDkuOTg5MiA2MC4wNDM2IDQ5Ljc1MTVDNjAuMzE0IDQ3LjgxMzYgNjAuNTg0NCA0NS44NzU3IDYwLjg1NDggNDMuOTM3OUM2MC44OTAxIDQzLjcxMiA2MC45MTM2IDQzLjQ4NjEgNjAuOTQ4OSA0My4yNjAyQzYxLjA5IDQyLjQxNjEgNjEuNTYwMiA0MiA2Mi4zNzE0IDQyQzY0LjQ0MDYgNDIgNjYuNTA5NyA0MiA2OC41Nzg5IDQyQzY5LjkwNzQgNDIgNzEuMjQ3NiA0MiA3Mi41NzYxIDQyQzczLjQ0NjEgNDIgNzMuOTI4MSA0Mi40NTE4IDc0LjA1NzUgNDMuMzMxNUM3NC4zNTE0IDQ1LjQzNTggNzQuNjQ1MyA0Ny41NDAyIDc0LjkyNzQgNDkuNjQ0NUM3NC45NzQ1IDQ5Ljk4OTIgNzUuMTE1NSA1MC4xNzk1IDc1LjQzMyA1MC4zMzRDNzYuNzM4IDUwLjkxNjYgNzcuOTcyNCA1MS42Mjk5IDc5LjExMjggNTIuNTA5NkM3OS4zNTk3IDUyLjY5OTkgNzkuNTU5NSA1Mi43MjM2IDc5Ljg0MTcgNTIuNjA0OEM4MS44MDUgNTEuNzk2MyA4My43Njg0IDUwLjk4NzkgODUuNzQzNSA1MC4xOTEzQzg2LjY3MjMgNDkuODEwOSA4Ny4yMTMxIDUwLjAxMyA4Ny43MTg2IDUwLjg5MjhDODkuMzc2MyA1My44MDU1IDkxLjAzMzkgNTYuNzE4MyA5Mi42OTE2IDU5LjYxOTFDOTMuMTczNiA2MC40NTEzIDkzLjA2NzggNjEuMDIyIDkyLjMxNTQgNjEuNjI4M0M5MC42NDYgNjIuOTU5OCA4OC45NzY1IDY0LjI3OTUgODcuMjk1NCA2NS41ODczQzg3LjAyNDkgNjUuODAxMyA4Ni45NDI3IDY2LjAyNzEgODYuOTc3OSA2Ni4zNkM4Ny4xNTQzIDY3Ljc4NjcgODcuMTU0MyA2OS4yMTMzIDg2Ljk3NzkgNzAuNjRDODYuOTQyNyA3MC45NjEgODcuMDI1IDcxLjE4NjkgODcuMjgzNiA3MS4zODlDODguOTI5NSA3Mi42ODQ4IDkwLjU3NTQgNzMuOTkyNiA5Mi4yMjE0IDc1LjMwMDRDOTMuMDU2MSA3NS45NjYxIDkzLjE2MTkgNzYuNDg5MiA5Mi42MzI4IDc3LjQxNjZDOTAuOTc1MiA4MC4zNDEyIDg5LjMwNTcgODMuMjUzOSA4Ny42MzYzIDg2LjE2NjdDODcuMTg5NSA4Ni45NTEzIDg2LjYwMTcgODcuMTUzNCA4NS43NjcgODYuODA4N0M4My44MDM3IDg2LjAxMjEgODEuODUyMSA4NS4yMTU2IDc5LjkwMDUgODQuNDA3MUM3OS41NzEzIDg0LjI2NDUgNzkuMzI0NCA4NC4yODgyIDc5LjAzMDUgODQuNTE0MUM3Ny45MDE5IDg1LjM5MzkgNzYuNjc5MiA4Ni4wOTUzIDc1LjM3NDIgODYuNjY2Qzc1LjA2ODUgODYuNzk2OCA3NC45MzkyIDg2Ljk4NyA3NC44OTIyIDg3LjMwOEM3NC42MSA4OS40MDA0IDc0LjMxNjEgOTEuNDkyOCA3NC4wMTA0IDkzLjU4NTJDNzMuOTYzNCA5My45MDYyIDczLjgzNDEgOTQuMjI3MiA3My42Njk1IDk0LjUwMDdDNzMuNDM0NCA5NC44NTczIDczLjA1ODEgOTQuOTg4MSA3Mi42MjMxIDk0Ljk4ODFDNzAuOTA2NyA5NC45ODgxIDY5LjE3ODUgOTQuOTg4MSA2Ny40NjIgOTQuOTg4MUg2Ny40ODU1Wk02Ny40NzM4IDU5LjE1NTVDNjIuNDMwMiA1OS4xNTU1IDU4LjI2ODQgNjMuMzUyMiA1OC4yNTY2IDY4LjQ2NDNDNTguMjQ0OSA3My42MDAzIDYyLjQwNjcgNzcuODIwOCA2Ny40ODU1IDc3LjgyMDhDNzIuNTUyNiA3Ny44MjA4IDc2LjcxNDQgNzMuNjEyMiA3Ni43MTQ0IDY4LjQ4ODFDNzYuNzE0NCA2My4zNDAzIDcyLjU2NDQgNTkuMTU1NSA2Ny40NjIgNTkuMTQzNkw2Ny40NzM4IDU5LjE1NTVaIiBmaWxsPSIjRkZGNUQ5Ii8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMTgyMV85MDkzIj4KPHJlY3Qgd2lkdGg9IjUxIiBoZWlnaHQ9IjUzIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDIgNDIpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg== \ No newline at end of file diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs new file mode 100644 index 00000000..1f06572e --- /dev/null +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -0,0 +1,291 @@ +use kinode_process_lib::{ + await_message, call_init, eth, get_blob, homepage, http, kernel_types, net, println, Address, + LazyLoadBlob, Message, NodeId, ProcessId, Request, Response, SendError, SendErrorKind, +}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +const ICON: &str = include_str!("icon"); + +#[derive(Debug, Serialize, Deserialize)] +struct ContactsState { + our: Address, +} + +impl ContactsState { + fn new(our: Address) -> Self { + Self { our } + } +} + +wit_bindgen::generate!({ + path: "target/wit", + world: "process-v0", +}); + +call_init!(initialize); +fn initialize(our: Address) { + // add ourselves to the homepage + homepage::add_to_homepage("Contacts", Some(ICON), Some("/"), None); + + // Grab our state, then enter the main event loop. + let mut state: ContactsState = ContactsState::new(our); + + let mut http_server = http::server::HttpServer::new(5); + + // Serve the index.html and other UI files found in pkg/ui at the root path. + // Serving securely at `settings-sys` subdomain + http_server + .serve_ui( + &state.our, + "ui", + vec!["/"], + http::server::HttpBindingConfig::default().secure_subdomain(true), + ) + .unwrap(); + http_server.secure_bind_http_path("/ask").unwrap(); + http_server.secure_bind_ws_path("/").unwrap(); + + main_loop(&mut state, &mut http_server); +} + +fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServer) { + loop { + match await_message() { + Err(send_error) => { + println!("got send error: {send_error:?}"); + continue; + } + Ok(Message::Request { + source, + body, + expects_response, + .. + }) => { + if source.node() != state.our.node { + continue; // ignore messages from other nodes + } + let response = handle_request(&source, &body, state, http_server); + // state.ws_update(http_server); + if expects_response.is_some() { + Response::new() + .body(serde_json::to_vec(&response).unwrap()) + .send() + .unwrap(); + } + } + _ => continue, // ignore responses + } + } +} + +fn handle_request( + source: &Address, + body: &[u8], + state: &mut ContactsState, + http_server: &mut http::server::HttpServer, +) -> SettingsResponse { + // source node is ALWAYS ourselves since networking is disabled + if source.process == "http_server:distro:sys" { + // receive HTTP requests and websocket connection messages from our server + let server_request = http_server + .parse_request(body) + .map_err(|_| SettingsError::MalformedRequest)?; + + http_server.handle_request( + server_request, + |req| { + let result = handle_http_request(state, &req); + match result { + Ok((resp, blob)) => (resp, blob), + Err(e) => { + println!("error handling HTTP request: {e}"); + ( + http::server::HttpResponse { + status: 500, + headers: HashMap::new(), + }, + Some(LazyLoadBlob { + mime: Some("application/text".to_string()), + bytes: e.to_string().as_bytes().to_vec(), + }), + ) + } + } + }, + |_channel_id, _message_type, _blob| { + // we don't expect websocket messages + }, + ); + Ok(None) + } else { + let settings_request = serde_json::from_slice::(body) + .map_err(|_| SettingsError::MalformedRequest)?; + handle_settings_request(state, settings_request) + } +} + +/// Handle HTTP requests from our own frontend. +fn handle_http_request( + state: &mut ContactsState, + http_request: &http::server::IncomingHttpRequest, +) -> anyhow::Result<(http::server::HttpResponse, Option)> { + match http_request.method()?.as_str() { + "GET" => { + state.fetch()?; + Ok(( + http::server::HttpResponse::new(http::StatusCode::OK) + .header("Content-Type", "application/json"), + Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(&state)?, + )), + )) + } + "POST" => { + let Some(blob) = get_blob() else { + return Err(anyhow::anyhow!("malformed request")); + }; + let request = serde_json::from_slice::(&blob.bytes)?; + let response = handle_settings_request(state, request); + Ok(( + http::server::HttpResponse::new(http::StatusCode::OK) + .header("Content-Type", "application/json"), + match response { + Ok(Some(data)) => Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(&data)?, + )), + Ok(None) => None, + Err(e) => Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(&e)?, + )), + }, + )) + } + // Any other method will be rejected. + _ => Ok(( + http::server::HttpResponse::new(http::StatusCode::METHOD_NOT_ALLOWED), + None, + )), + } +} + +fn handle_settings_request( + state: &mut SettingsState, + request: SettingsRequest, +) -> SettingsResponse { + match request { + SettingsRequest::Hi { + node, + content, + timeout, + } => { + if let Err(SendError { kind, .. }) = Request::to((&node, "net", "distro", "sys")) + .body(content.into_bytes()) + .send_and_await_response(timeout) + .unwrap() + { + match kind { + SendErrorKind::Timeout => { + println!("message to {node} timed out"); + return Err(SettingsError::HiTimeout); + } + SendErrorKind::Offline => { + println!("{node} is offline or does not exist"); + return Err(SettingsError::HiOffline); + } + } + } else { + return Ok(None); + } + } + SettingsRequest::PeerId(node) => { + // get peer info + match Request::to(("our", "net", "distro", "sys")) + .body(rmp_serde::to_vec(&net::NetAction::GetPeer(node)).unwrap()) + .send_and_await_response(30) + .unwrap() + { + Ok(msg) => match rmp_serde::from_slice::(msg.body()) { + Ok(net::NetResponse::Peer(Some(peer))) => { + println!("got peer info: {peer:?}"); + return Ok(Some(SettingsData::PeerId(peer))); + } + Ok(net::NetResponse::Peer(None)) => { + println!("peer not found"); + return Ok(None); + } + _ => { + return Err(SettingsError::KernelNonresponsive); + } + }, + Err(_) => { + return Err(SettingsError::KernelNonresponsive); + } + } + } + SettingsRequest::EthConfig(action) => { + match Request::to(("our", "eth", "distro", "sys")) + .body(serde_json::to_vec(&action).unwrap()) + .send_and_await_response(30) + .unwrap() + { + Ok(msg) => match serde_json::from_slice::(msg.body()) { + Ok(eth::EthConfigResponse::PermissionDenied) => { + return Err(SettingsError::KernelNonresponsive); + } + Ok(other) => { + println!("eth config action succeeded: {other:?}"); + } + Err(_) => { + return Err(SettingsError::KernelNonresponsive); + } + }, + Err(_) => { + return Err(SettingsError::KernelNonresponsive); + } + } + } + SettingsRequest::Shutdown => { + // shutdown the node IMMEDIATELY! + Request::to(("our", "kernel", "distro", "sys")) + .body(serde_json::to_vec(&kernel_types::KernelCommand::Shutdown).unwrap()) + .send() + .unwrap(); + } + SettingsRequest::KillProcess(pid) => { + // kill a process + if let Err(_) = Request::to(("our", "kernel", "distro", "sys")) + .body(serde_json::to_vec(&kernel_types::KernelCommand::KillProcess(pid)).unwrap()) + .send_and_await_response(30) + .unwrap() + { + return SettingsResponse::Err(SettingsError::KernelNonresponsive); + } + } + SettingsRequest::SetStylesheet(stylesheet) => { + let Ok(()) = kinode_process_lib::vfs::File { + path: "/homepage:sys/pkg/kinode.css".to_string(), + timeout: 5, + } + .write(stylesheet.as_bytes()) else { + return SettingsResponse::Err(SettingsError::KernelNonresponsive); + }; + Request::to(("our", "homepage", "homepage", "sys")) + .body( + serde_json::json!({ "SetStylesheet": stylesheet }) + .to_string() + .as_bytes(), + ) + .send() + .unwrap(); + state.stylesheet = Some(stylesheet); + return SettingsResponse::Ok(None); + } + } + + state.fetch().map_err(|_| SettingsError::StateFetchFailed)?; + SettingsResponse::Ok(None) +} diff --git a/kinode/packages/contacts/metadata.json b/kinode/packages/contacts/metadata.json new file mode 100644 index 00000000..85ee4548 --- /dev/null +++ b/kinode/packages/contacts/metadata.json @@ -0,0 +1,18 @@ +{ + "name": "Contacts", + "description": "Store and manage your contacts.", + "image": "", + "properties": { + "package_name": "contacts", + "current_version": "0.1.0", + "publisher": "sys", + "mirrors": [], + "code_hashes": { + "0.1.0": "" + }, + "wit_version": 0, + "dependencies": [] + }, + "external_url": "https://kinode.org", + "animation_url": "" +} \ No newline at end of file diff --git a/kinode/packages/contacts/pkg/manifest.json b/kinode/packages/contacts/pkg/manifest.json new file mode 100644 index 00000000..4d28b723 --- /dev/null +++ b/kinode/packages/contacts/pkg/manifest.json @@ -0,0 +1,18 @@ +[ + { + "process_name": "contacts", + "process_wasm_path": "/contacts.wasm", + "on_exit": "Restart", + "request_networking": false, + "request_capabilities": [ + "homepage:homepage:sys", + "http_server:distro:sys", + "vfs:distro:sys" + ], + "grant_capabilities": [ + "http_server:distro:sys", + "vfs:distro:sys" + ], + "public": false + } +] \ No newline at end of file diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html new file mode 100644 index 00000000..38c627fa --- /dev/null +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + +

system diagnostics & settings

+
+
+

networking diagnostics

+

+
+ +
+

node info

+

+

+

+

+ +
+ +
+

fetch PKI data

+
+ + +
+

+

ping a node

+
+ + + + +
+

+
+ +
+

ETH RPC providers

+
+
+ + + +
+
+ + + +
+
+
    +
    + +
    +

    ETH RPC settings

    +

    +
    +

    nodes allowed to connect:

    +
      +
      +
      +

      nodes banned from connecting:

      +
        +
        +
        + +
        +

        running processes

        +
          +
          + +
          +

          stylesheet editor

          + + +
          + + + +
          + + + \ No newline at end of file diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js new file mode 100644 index 00000000..01ebb557 --- /dev/null +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -0,0 +1,320 @@ +const APP_PATH = '/settings:settings:sys/ask'; + +// Fetch initial data and populate the UI +function init() { + fetch(APP_PATH) + .then(response => response.json()) + .then(data => { + populate(data); + }); +} + +function api_call(body) { + fetch(APP_PATH, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); +} + +function shutdown() { + api_call("Shutdown"); + setTimeout(() => { + window.location.reload(); + }, 1000); +} + +function populate(data) { + populate_node_info(data.identity); + populate_net_diagnostics(data.diagnostics); + populate_eth_rpc_providers(data.eth_rpc_providers); + populate_eth_rpc_settings(data.eth_rpc_access_settings); + populate_process_map(data.process_map); + populate_stylesheet_editor(data.stylesheet); +} + +function populate_node_info(identity) { + document.getElementById('node-name').innerText = identity.name; + document.getElementById('net-key').innerText = identity.networking_key; + if (identity.ws_routing) { + document.getElementById('ip-ports').innerText = identity.ws_routing; + } else { + document.getElementById('ip-ports').style.display = 'none'; + } + if (identity.routers) { + document.getElementById('routers').innerText = identity.routers; + } else { + document.getElementById('routers').style.display = 'none'; + } +} + +function populate_net_diagnostics(diagnostics) { + document.getElementById('diagnostics').innerText = diagnostics; +} + +function populate_eth_rpc_providers(providers) { + const ul = document.getElementById('providers'); + ul.innerHTML = ''; + providers.forEach(provider => { + const li = document.createElement('li'); + li.innerHTML = `${JSON.stringify(provider, undefined, 2)}`; + ul.appendChild(li); + }); +} + +function populate_eth_rpc_settings(settings) { + if (settings.public) { + document.getElementById('public').innerText = 'status: public'; + document.getElementById('allowed-nodes').style.display = 'none'; + } else { + document.getElementById('public').innerText = 'status: private'; + const ul = document.getElementById('allowed-nodes'); + ul.innerHTML = ''; + if (settings.allow.length === 0) { + const li = document.createElement('li'); + li.innerHTML = `
        • (none)
        • `; + ul.appendChild(li); + } else { + settings.allow.forEach(allowed_node => { + const li = document.createElement('li'); + li.innerHTML = `
        • ${allowed_node}
        • `; + ul.appendChild(li); + }); + } + } + const ul = document.getElementById('denied-nodes'); + ul.innerHTML = ''; + if (settings.deny.length === 0) { + const li = document.createElement('li'); + li.innerHTML = `
        • (none)
        • `; + ul.appendChild(li); + } else { + settings.deny.forEach(denied_node => { + const li = document.createElement('li'); + li.innerHTML = `
        • ${denied_node}
        • `; + ul.appendChild(li); + }); + } +} + +function populate_process_map(process_map) { + // apps we don't want user to kill, also runtime modules that cannot be killed + const do_not_kill = [ + 'settings:setting:sys', + 'main:app_store:sys', + 'net:distro:sys', + 'kernel:distro:sys', + 'kv:distro:sys', + 'sqlite:distro:sys', + 'eth:distro:sys', + 'vfs:distro:sys', + 'state:distro:sys', + 'kns_indexer:kns_indexer:sys', + 'http_client:distro:sys', + 'http_server:distro:sys', + 'terminal:terminal:sys', + 'timer:distro:sys', + ]; + + const ul = document.getElementById('process-map'); + ul.innerHTML = ''; + Object.entries(process_map).forEach(([id, process]) => { + const li = document.createElement('li'); + + const toggleButton = document.createElement('button'); + toggleButton.textContent = `${id}`; + toggleButton.onclick = function () { + const details = this.nextElementSibling; + details.style.display = details.style.display === 'none' ? 'block' : 'none'; + }; + li.appendChild(toggleButton); + + const detailsDiv = document.createElement('div'); + detailsDiv.style.display = 'none'; + + if (!do_not_kill.includes(id)) { + const killButton = document.createElement('button'); + killButton.className = 'kill-process'; + killButton.setAttribute('data-id', id); + killButton.textContent = 'kill'; + detailsDiv.appendChild(killButton); + } + + const publicInfo = document.createElement('p'); + publicInfo.textContent = `public: ${process.public}`; + detailsDiv.appendChild(publicInfo); + + const onExit = document.createElement('p'); + onExit.textContent = `on_exit: ${process.on_exit}`; + detailsDiv.appendChild(onExit); + + if (process.wit_version) { + const witVersion = document.createElement('p'); + witVersion.textContent = `wit_version: ${process.wit_version}`; + detailsDiv.appendChild(witVersion); + } + + if (process.wasm_bytes_handle) { + const wasmBytesHandle = document.createElement('p'); + wasmBytesHandle.textContent = `wasm_bytes_handle: ${process.wasm_bytes_handle}`; + detailsDiv.appendChild(wasmBytesHandle); + } + + const capsList = document.createElement('ul'); + process.capabilities.forEach(cap => { + const capLi = document.createElement('li'); + capLi.textContent = `${cap.issuer}(${JSON.stringify(JSON.parse(cap.params), null, 2)})`; + capsList.appendChild(capLi); + }); + detailsDiv.appendChild(capsList); + + li.appendChild(detailsDiv); + ul.appendChild(li); + }); + document.querySelectorAll('.kill-process').forEach(button => { + button.addEventListener('click', () => { + api_call({ "KillProcess": button.getAttribute('data-id') }); + }); + }); +} + +function populate_stylesheet_editor(stylesheet) { + document.getElementById('stylesheet-editor').value = stylesheet; +} + +function save_stylesheet() { + const stylesheet = document.getElementById('stylesheet-editor').value; + api_call({ "SetStylesheet": stylesheet }); +} + +// Call init to start the application +init(); + +// Setup event listeners +document.getElementById('shutdown').addEventListener('click', shutdown); + +document.getElementById('save-stylesheet').addEventListener('click', save_stylesheet); + +document.getElementById('get-peer-pki').addEventListener('submit', (e) => { + e.preventDefault(); + const data = new FormData(e.target); + const body = { + "PeerId": data.get('peer'), + }; + fetch(APP_PATH, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }).then(response => response.json()) + .then(data => { + if (data === null) { + document.getElementById('peer-pki-response').innerText = "no pki data for peer"; + } else { + e.target.reset(); + document.getElementById('peer-pki-response').innerText = JSON.stringify(data, undefined, 2); + } + }); +}) + +document.getElementById('ping-peer').addEventListener('submit', (e) => { + e.preventDefault(); + const data = new FormData(e.target); + const body = { + "Hi": { + node: data.get('peer'), + content: data.get('content'), + timeout: Number(data.get('timeout')), + } + }; + fetch(APP_PATH, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }).then(response => response.json()) + .then(data => { + if (data === null) { + e.target.reset(); + document.getElementById('peer-ping-response').innerText = "ping successful!"; + } else if (data === "HiTimeout") { + document.getElementById('peer-ping-response').innerText = "node timed out"; + } else if (data === "HiOffline") { + document.getElementById('peer-ping-response').innerText = "node is offline"; + } + }); +}) + +document.getElementById('add-eth-provider').addEventListener('submit', (e) => { + e.preventDefault(); + const data = new FormData(e.target); + const rpc_url = data.get('rpc-url'); + // validate rpc url + if (!rpc_url.startsWith('wss://') && !rpc_url.startsWith('ws://')) { + alert('Invalid RPC URL'); + return; + } + const body = { + "EthConfig": { + "AddProvider": { + chain_id: Number(data.get('chain-id')), + trusted: false, + provider: { "RpcUrl": rpc_url }, + } + } + }; + fetch(APP_PATH, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }).then(response => response.json()) + .then(data => { + if (data === null) { + e.target.reset(); + return; + } else { + alert(data); + } + }); +}) + +document.getElementById('remove-eth-provider').addEventListener('submit', (e) => { + e.preventDefault(); + const data = new FormData(e.target); + const body = { + "EthConfig": { + "RemoveProvider": [Number(data.get('chain-id')), data.get('rpc-url')] + } + }; + fetch(APP_PATH, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }).then(response => response.json()) + .then(data => { + if (data === null) { + e.target.reset(); + return; + } else { + alert(data); + } + }); +}) + +// Setup WebSocket connection +const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; +const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/"); +ws.onmessage = event => { + const data = JSON.parse(event.data); + console.log(data); + populate(data); +}; + From 5486100e1d2184ec369c13d1e6a01365e30f9819 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Tue, 15 Oct 2024 16:46:21 -0400 Subject: [PATCH 02/13] real mvp --- Cargo.lock | 70 ++-- .../packages/contacts/api/contacts:sys-v0.wit | 35 ++ kinode/packages/contacts/contacts/Cargo.toml | 2 +- kinode/packages/contacts/contacts/src/lib.rs | 271 ++++++---------- kinode/packages/contacts/metadata.json | 2 +- kinode/packages/contacts/pkg/ui/index.html | 189 +---------- kinode/packages/contacts/pkg/ui/script.js | 307 +----------------- 7 files changed, 186 insertions(+), 690 deletions(-) create mode 100644 kinode/packages/contacts/api/contacts:sys-v0.wit diff --git a/Cargo.lock b/Cargo.lock index 16b1c638..601233b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,7 +78,7 @@ name = "alias" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -1012,7 +1012,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -1383,7 +1383,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "url", @@ -1592,7 +1592,7 @@ name = "cat" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -1656,7 +1656,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -1675,7 +1675,7 @@ version = "0.2.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "pleco", "serde", "serde_json", @@ -1867,7 +1867,7 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" name = "contacts" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -2443,7 +2443,7 @@ name = "download" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", @@ -2455,7 +2455,7 @@ name = "downloads" version = "0.5.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -2492,7 +2492,7 @@ dependencies = [ name = "echo" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "wit-bindgen", ] @@ -2731,7 +2731,7 @@ version = "0.2.0" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "rand 0.8.5", "serde", @@ -2885,7 +2885,7 @@ dependencies = [ name = "get_block" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -2950,7 +2950,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" name = "globe" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "url", @@ -3077,7 +3077,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" name = "help" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "wit-bindgen", ] @@ -3106,7 +3106,7 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" name = "hi" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -3139,7 +3139,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -3454,7 +3454,7 @@ name = "install" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", @@ -3631,7 +3631,7 @@ name = "kfetch" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "serde_json", @@ -3643,7 +3643,7 @@ name = "kill" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -3715,9 +3715,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c5b69ac1fc0cb457c7714ceb8c0a5bdbee4ee00b837f9f16ea711e902bdfe8" +version = "0.9.2" +source = "git+https://github.com/kinode-dao/process_lib.git?rev=9ac9e51#9ac9e513c0228f2dcfe8999ed4ca2c38246ee3db" dependencies = [ "alloy 0.1.4", "alloy-primitives", @@ -3738,8 +3737,9 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.2" -source = "git+https://github.com/kinode-dao/process_lib.git?rev=9ac9e51#9ac9e513c0228f2dcfe8999ed4ca2c38246ee3db" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7722aef4bff0625445fafda89a02f82ce0e16c7def6024e1317ae55a632ad331" dependencies = [ "alloy 0.1.4", "alloy-primitives", @@ -3840,7 +3840,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "hex", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "serde_json", @@ -4067,7 +4067,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "regex", "serde", "serde_json", @@ -4237,7 +4237,7 @@ dependencies = [ name = "net_diagnostics" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "wit-bindgen", @@ -4563,7 +4563,7 @@ dependencies = [ name = "peer" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "wit-bindgen", @@ -4573,7 +4573,7 @@ dependencies = [ name = "peers" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "wit-bindgen", @@ -5614,7 +5614,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rmp-serde", "serde", "serde_json", @@ -5832,7 +5832,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "state" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -6009,7 +6009,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "rand 0.8.5", "regex", "serde", @@ -6023,7 +6023,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", @@ -6280,7 +6280,7 @@ version = "0.2.0" dependencies = [ "anyhow", "clap", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "serde", "serde_json", "wit-bindgen", @@ -6611,7 +6611,7 @@ name = "uninstall" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.1", + "kinode_process_lib 0.9.3", "process_macros", "serde", "serde_json", diff --git a/kinode/packages/contacts/api/contacts:sys-v0.wit b/kinode/packages/contacts/api/contacts:sys-v0.wit new file mode 100644 index 00000000..a689775b --- /dev/null +++ b/kinode/packages/contacts/api/contacts:sys-v0.wit @@ -0,0 +1,35 @@ +interface contacts { + enum capabilities { + read-name-only, + read, + add, + remove, + } + + variant contacts-request { + get-names, // requires read-names-only + get-all-contacts, // requires read + get-contact(string), // requires read + add-contact(string), // requires add + // tuple + add-field(tuple), // requires add + remove-contact(string), // requires remove + // tuple + remove-field(tuple), // requires remove + } + + variant contacts-response { + get-names(list), + get-all-contacts, // JSON all-contacts dict in blob + get-contact, // JSON contact dict in blob + add-contact, + add-field, + remove-contact, + remove-field, + } +} + +world contacts-sys-v0 { + import contacts; + include process-v0; +} diff --git a/kinode/packages/contacts/contacts/Cargo.toml b/kinode/packages/contacts/contacts/Cargo.toml index c8704114..54c6bada 100644 --- a/kinode/packages/contacts/contacts/Cargo.toml +++ b/kinode/packages/contacts/contacts/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = "0.9.1" +kinode_process_lib = "0.9.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index 1f06572e..b407bd55 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -1,40 +1,85 @@ +use crate::kinode::process::contacts::{ContactsRequest, ContactsResponse}; use kinode_process_lib::{ - await_message, call_init, eth, get_blob, homepage, http, kernel_types, net, println, Address, - LazyLoadBlob, Message, NodeId, ProcessId, Request, Response, SendError, SendErrorKind, + await_message, call_init, get_blob, get_typed_state, homepage, http, println, set_state, + Address, LazyLoadBlob, Message, NodeId, Response, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; const ICON: &str = include_str!("icon"); +#[derive(Debug, Serialize, Deserialize)] +struct Contact(HashMap); + +#[derive(Debug, Serialize, Deserialize)] +struct Contacts(HashMap); + #[derive(Debug, Serialize, Deserialize)] struct ContactsState { our: Address, + contacts: Contacts, } impl ContactsState { fn new(our: Address) -> Self { - Self { our } + get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self { + our, + contacts: Contacts(HashMap::new()), + }) + } + + fn save(&self) { + set_state(&serde_json::to_vec(&self).expect("Failed to serialize contacts state!")); + } + + fn contacts(&self) -> &Contacts { + &self.contacts + } + + fn get_contact(&self, node: NodeId) -> Option<&Contact> { + self.contacts.0.get(&node) + } + + fn add_contact(&mut self, node: NodeId) { + self.contacts.0.insert(node, Contact(HashMap::new())); + } + + fn remove_contact(&mut self, node: NodeId) { + self.contacts.0.remove(&node); + } + + fn add_field(&mut self, node: NodeId, field: String, value: serde_json::Value) { + self.contacts + .0 + .entry(node) + .or_insert_with(|| Contact(HashMap::new())) + .0 + .insert(field, value); + } + + fn remove_field(&mut self, node: NodeId, field: String) { + if let Some(contact) = self.contacts.0.get_mut(&node) { + contact.0.remove(&field); + } } } wit_bindgen::generate!({ path: "target/wit", - world: "process-v0", + world: "contacts-sys-v0", + generate_unused_types: true, + additional_derives: [PartialEq, serde::Deserialize, serde::Serialize], }); call_init!(initialize); fn initialize(our: Address) { - // add ourselves to the homepage homepage::add_to_homepage("Contacts", Some(ICON), Some("/"), None); - // Grab our state, then enter the main event loop. let mut state: ContactsState = ContactsState::new(our); let mut http_server = http::server::HttpServer::new(5); - // Serve the index.html and other UI files found in pkg/ui at the root path. - // Serving securely at `settings-sys` subdomain + // serve the frontend on a secure subdomain http_server .serve_ui( &state.our, @@ -52,8 +97,8 @@ fn initialize(our: Address) { fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServer) { loop { match await_message() { - Err(send_error) => { - println!("got send error: {send_error:?}"); + Err(_send_error) => { + // ignore send errors, local-only process continue; } Ok(Message::Request { @@ -84,44 +129,25 @@ fn handle_request( body: &[u8], state: &mut ContactsState, http_server: &mut http::server::HttpServer, -) -> SettingsResponse { +) -> Option { // source node is ALWAYS ourselves since networking is disabled if source.process == "http_server:distro:sys" { // receive HTTP requests and websocket connection messages from our server - let server_request = http_server - .parse_request(body) - .map_err(|_| SettingsError::MalformedRequest)?; + let server_request = http_server.parse_request(body).unwrap(); http_server.handle_request( server_request, - |req| { - let result = handle_http_request(state, &req); - match result { - Ok((resp, blob)) => (resp, blob), - Err(e) => { - println!("error handling HTTP request: {e}"); - ( - http::server::HttpResponse { - status: 500, - headers: HashMap::new(), - }, - Some(LazyLoadBlob { - mime: Some("application/text".to_string()), - bytes: e.to_string().as_bytes().to_vec(), - }), - ) - } - } - }, + |req| handle_http_request(state, &req), |_channel_id, _message_type, _blob| { // we don't expect websocket messages }, ); - Ok(None) + None } else { - let settings_request = serde_json::from_slice::(body) - .map_err(|_| SettingsError::MalformedRequest)?; - handle_settings_request(state, settings_request) + // let settings_request = serde_json::from_slice::(body) + // .map_err(|_| SettingsError::MalformedRequest)?; + // handle_settings_request(state, settings_request) + None } } @@ -129,163 +155,62 @@ fn handle_request( fn handle_http_request( state: &mut ContactsState, http_request: &http::server::IncomingHttpRequest, -) -> anyhow::Result<(http::server::HttpResponse, Option)> { - match http_request.method()?.as_str() { +) -> (http::server::HttpResponse, Option) { + match http_request.method().unwrap().as_str() { "GET" => { - state.fetch()?; - Ok(( + // state.fetch().unwrap(); + ( http::server::HttpResponse::new(http::StatusCode::OK) .header("Content-Type", "application/json"), Some(LazyLoadBlob::new( Some("application/json"), - serde_json::to_vec(&state)?, + serde_json::to_vec(&state).unwrap(), )), - )) + ) } "POST" => { - let Some(blob) = get_blob() else { - return Err(anyhow::anyhow!("malformed request")); - }; - let request = serde_json::from_slice::(&blob.bytes)?; - let response = handle_settings_request(state, request); - Ok(( + let blob = get_blob().unwrap(); + let request = serde_json::from_slice::(&blob.bytes).unwrap(); + let response = handle_contacts_request(state, request); + let response: Option = Some("ok".to_string()); + ( http::server::HttpResponse::new(http::StatusCode::OK) .header("Content-Type", "application/json"), match response { - Ok(Some(data)) => Some(LazyLoadBlob::new( + Some(data) => Some(LazyLoadBlob::new( Some("application/json"), - serde_json::to_vec(&data)?, - )), - Ok(None) => None, - Err(e) => Some(LazyLoadBlob::new( - Some("application/json"), - serde_json::to_vec(&e)?, + serde_json::to_vec(&data).unwrap(), )), + None => None, }, - )) + ) } // Any other method will be rejected. - _ => Ok(( + _ => ( http::server::HttpResponse::new(http::StatusCode::METHOD_NOT_ALLOWED), None, - )), + ), } } -fn handle_settings_request( - state: &mut SettingsState, - request: SettingsRequest, -) -> SettingsResponse { +fn handle_contacts_request( + state: &mut ContactsState, + request: ContactsRequest, +) -> ContactsResponse { match request { - SettingsRequest::Hi { - node, - content, - timeout, - } => { - if let Err(SendError { kind, .. }) = Request::to((&node, "net", "distro", "sys")) - .body(content.into_bytes()) - .send_and_await_response(timeout) - .unwrap() - { - match kind { - SendErrorKind::Timeout => { - println!("message to {node} timed out"); - return Err(SettingsError::HiTimeout); - } - SendErrorKind::Offline => { - println!("{node} is offline or does not exist"); - return Err(SettingsError::HiOffline); - } - } - } else { - return Ok(None); - } - } - SettingsRequest::PeerId(node) => { - // get peer info - match Request::to(("our", "net", "distro", "sys")) - .body(rmp_serde::to_vec(&net::NetAction::GetPeer(node)).unwrap()) - .send_and_await_response(30) - .unwrap() - { - Ok(msg) => match rmp_serde::from_slice::(msg.body()) { - Ok(net::NetResponse::Peer(Some(peer))) => { - println!("got peer info: {peer:?}"); - return Ok(Some(SettingsData::PeerId(peer))); - } - Ok(net::NetResponse::Peer(None)) => { - println!("peer not found"); - return Ok(None); - } - _ => { - return Err(SettingsError::KernelNonresponsive); - } - }, - Err(_) => { - return Err(SettingsError::KernelNonresponsive); - } - } - } - SettingsRequest::EthConfig(action) => { - match Request::to(("our", "eth", "distro", "sys")) - .body(serde_json::to_vec(&action).unwrap()) - .send_and_await_response(30) - .unwrap() - { - Ok(msg) => match serde_json::from_slice::(msg.body()) { - Ok(eth::EthConfigResponse::PermissionDenied) => { - return Err(SettingsError::KernelNonresponsive); - } - Ok(other) => { - println!("eth config action succeeded: {other:?}"); - } - Err(_) => { - return Err(SettingsError::KernelNonresponsive); - } - }, - Err(_) => { - return Err(SettingsError::KernelNonresponsive); - } - } - } - SettingsRequest::Shutdown => { - // shutdown the node IMMEDIATELY! - Request::to(("our", "kernel", "distro", "sys")) - .body(serde_json::to_vec(&kernel_types::KernelCommand::Shutdown).unwrap()) - .send() - .unwrap(); - } - SettingsRequest::KillProcess(pid) => { - // kill a process - if let Err(_) = Request::to(("our", "kernel", "distro", "sys")) - .body(serde_json::to_vec(&kernel_types::KernelCommand::KillProcess(pid)).unwrap()) - .send_and_await_response(30) - .unwrap() - { - return SettingsResponse::Err(SettingsError::KernelNonresponsive); - } - } - SettingsRequest::SetStylesheet(stylesheet) => { - let Ok(()) = kinode_process_lib::vfs::File { - path: "/homepage:sys/pkg/kinode.css".to_string(), - timeout: 5, - } - .write(stylesheet.as_bytes()) else { - return SettingsResponse::Err(SettingsError::KernelNonresponsive); - }; - Request::to(("our", "homepage", "homepage", "sys")) - .body( - serde_json::json!({ "SetStylesheet": stylesheet }) - .to_string() - .as_bytes(), - ) - .send() - .unwrap(); - state.stylesheet = Some(stylesheet); - return SettingsResponse::Ok(None); - } + ContactsRequest::GetNames => ContactsResponse::GetNames( + state + .contacts() + .0 + .keys() + .map(|node| node.to_string()) + .collect(), + ), + ContactsRequest::GetAllContacts => ContactsResponse::GetAllContacts, + ContactsRequest::GetContact(node) => ContactsResponse::GetContact, + ContactsRequest::AddContact(node) => ContactsResponse::AddContact, + ContactsRequest::AddField((node, field, value)) => ContactsResponse::AddField, + ContactsRequest::RemoveContact(node) => ContactsResponse::RemoveContact, + ContactsRequest::RemoveField((node, field)) => ContactsResponse::RemoveField, } - - state.fetch().map_err(|_| SettingsError::StateFetchFailed)?; - SettingsResponse::Ok(None) } diff --git a/kinode/packages/contacts/metadata.json b/kinode/packages/contacts/metadata.json index 85ee4548..c3a7a181 100644 --- a/kinode/packages/contacts/metadata.json +++ b/kinode/packages/contacts/metadata.json @@ -1,6 +1,6 @@ { "name": "Contacts", - "description": "Store and manage your contacts.", + "description": "Save and manage your Kinode OS contacts.", "image": "", "properties": { "package_name": "contacts", diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html index 38c627fa..e6dcb5ad 100644 --- a/kinode/packages/contacts/pkg/ui/index.html +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -6,13 +6,10 @@ - + -

          system diagnostics & settings

          +

          contacts

          -
          -

          networking diagnostics

          -

          -
          - -
          -

          node info

          -

          -

          -

          -

          - -
          - -
          -

          fetch PKI data

          -
          - - -
          -

          -

          ping a node

          -
          - - - - -
          -

          -
          - -
          -

          ETH RPC providers

          -
          -
          - - - -
          -
          - - - -
          -
          -
            -
            - -
            -

            ETH RPC settings

            -

            -
            -

            nodes allowed to connect:

            -
              -
              -
              -

              nodes banned from connecting:

              -
                -
                -
                - -
                -

                running processes

                -
                  -
                  - -
                  -

                  stylesheet editor

                  - - -
                  - - - +
                  diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index 01ebb557..8f1376c5 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -1,16 +1,16 @@ -const APP_PATH = '/settings:settings:sys/ask'; +const APP_PATH = '/contacts:contacts:sys/'; // Fetch initial data and populate the UI function init() { - fetch(APP_PATH) + fetch(APP_PATH + 'get') .then(response => response.json()) .then(data => { populate(data); }); } -function api_call(body) { - fetch(APP_PATH, { +function api_call(path, body) { + fetch(APP_PATH + path, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -19,302 +19,19 @@ function api_call(body) { }); } -function shutdown() { - api_call("Shutdown"); - setTimeout(() => { - window.location.reload(); - }, 1000); -} - function populate(data) { - populate_node_info(data.identity); - populate_net_diagnostics(data.diagnostics); - populate_eth_rpc_providers(data.eth_rpc_providers); - populate_eth_rpc_settings(data.eth_rpc_access_settings); - populate_process_map(data.process_map); - populate_stylesheet_editor(data.stylesheet); -} - -function populate_node_info(identity) { - document.getElementById('node-name').innerText = identity.name; - document.getElementById('net-key').innerText = identity.networking_key; - if (identity.ws_routing) { - document.getElementById('ip-ports').innerText = identity.ws_routing; - } else { - document.getElementById('ip-ports').style.display = 'none'; - } - if (identity.routers) { - document.getElementById('routers').innerText = identity.routers; - } else { - document.getElementById('routers').style.display = 'none'; - } -} - -function populate_net_diagnostics(diagnostics) { - document.getElementById('diagnostics').innerText = diagnostics; -} - -function populate_eth_rpc_providers(providers) { - const ul = document.getElementById('providers'); - ul.innerHTML = ''; - providers.forEach(provider => { - const li = document.createElement('li'); - li.innerHTML = `${JSON.stringify(provider, undefined, 2)}`; - ul.appendChild(li); - }); -} - -function populate_eth_rpc_settings(settings) { - if (settings.public) { - document.getElementById('public').innerText = 'status: public'; - document.getElementById('allowed-nodes').style.display = 'none'; - } else { - document.getElementById('public').innerText = 'status: private'; - const ul = document.getElementById('allowed-nodes'); - ul.innerHTML = ''; - if (settings.allow.length === 0) { - const li = document.createElement('li'); - li.innerHTML = `
                • (none)
                • `; - ul.appendChild(li); - } else { - settings.allow.forEach(allowed_node => { - const li = document.createElement('li'); - li.innerHTML = `
                • ${allowed_node}
                • `; - ul.appendChild(li); - }); - } - } - const ul = document.getElementById('denied-nodes'); - ul.innerHTML = ''; - if (settings.deny.length === 0) { - const li = document.createElement('li'); - li.innerHTML = `
                • (none)
                • `; - ul.appendChild(li); - } else { - settings.deny.forEach(denied_node => { - const li = document.createElement('li'); - li.innerHTML = `
                • ${denied_node}
                • `; - ul.appendChild(li); - }); - } -} - -function populate_process_map(process_map) { - // apps we don't want user to kill, also runtime modules that cannot be killed - const do_not_kill = [ - 'settings:setting:sys', - 'main:app_store:sys', - 'net:distro:sys', - 'kernel:distro:sys', - 'kv:distro:sys', - 'sqlite:distro:sys', - 'eth:distro:sys', - 'vfs:distro:sys', - 'state:distro:sys', - 'kns_indexer:kns_indexer:sys', - 'http_client:distro:sys', - 'http_server:distro:sys', - 'terminal:terminal:sys', - 'timer:distro:sys', - ]; - - const ul = document.getElementById('process-map'); - ul.innerHTML = ''; - Object.entries(process_map).forEach(([id, process]) => { - const li = document.createElement('li'); - - const toggleButton = document.createElement('button'); - toggleButton.textContent = `${id}`; - toggleButton.onclick = function () { - const details = this.nextElementSibling; - details.style.display = details.style.display === 'none' ? 'block' : 'none'; - }; - li.appendChild(toggleButton); - - const detailsDiv = document.createElement('div'); - detailsDiv.style.display = 'none'; - - if (!do_not_kill.includes(id)) { - const killButton = document.createElement('button'); - killButton.className = 'kill-process'; - killButton.setAttribute('data-id', id); - killButton.textContent = 'kill'; - detailsDiv.appendChild(killButton); - } - - const publicInfo = document.createElement('p'); - publicInfo.textContent = `public: ${process.public}`; - detailsDiv.appendChild(publicInfo); - - const onExit = document.createElement('p'); - onExit.textContent = `on_exit: ${process.on_exit}`; - detailsDiv.appendChild(onExit); - - if (process.wit_version) { - const witVersion = document.createElement('p'); - witVersion.textContent = `wit_version: ${process.wit_version}`; - detailsDiv.appendChild(witVersion); - } - - if (process.wasm_bytes_handle) { - const wasmBytesHandle = document.createElement('p'); - wasmBytesHandle.textContent = `wasm_bytes_handle: ${process.wasm_bytes_handle}`; - detailsDiv.appendChild(wasmBytesHandle); - } - - const capsList = document.createElement('ul'); - process.capabilities.forEach(cap => { - const capLi = document.createElement('li'); - capLi.textContent = `${cap.issuer}(${JSON.stringify(JSON.parse(cap.params), null, 2)})`; - capsList.appendChild(capLi); - }); - detailsDiv.appendChild(capsList); - - li.appendChild(detailsDiv); - ul.appendChild(li); - }); - document.querySelectorAll('.kill-process').forEach(button => { - button.addEventListener('click', () => { - api_call({ "KillProcess": button.getAttribute('data-id') }); - }); - }); -} - -function populate_stylesheet_editor(stylesheet) { - document.getElementById('stylesheet-editor').value = stylesheet; -} - -function save_stylesheet() { - const stylesheet = document.getElementById('stylesheet-editor').value; - api_call({ "SetStylesheet": stylesheet }); + console.log(data); } // Call init to start the application init(); -// Setup event listeners -document.getElementById('shutdown').addEventListener('click', shutdown); - -document.getElementById('save-stylesheet').addEventListener('click', save_stylesheet); - -document.getElementById('get-peer-pki').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const body = { - "PeerId": data.get('peer'), - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - document.getElementById('peer-pki-response').innerText = "no pki data for peer"; - } else { - e.target.reset(); - document.getElementById('peer-pki-response').innerText = JSON.stringify(data, undefined, 2); - } - }); -}) - -document.getElementById('ping-peer').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const body = { - "Hi": { - node: data.get('peer'), - content: data.get('content'), - timeout: Number(data.get('timeout')), - } - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - e.target.reset(); - document.getElementById('peer-ping-response').innerText = "ping successful!"; - } else if (data === "HiTimeout") { - document.getElementById('peer-ping-response').innerText = "node timed out"; - } else if (data === "HiOffline") { - document.getElementById('peer-ping-response').innerText = "node is offline"; - } - }); -}) - -document.getElementById('add-eth-provider').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const rpc_url = data.get('rpc-url'); - // validate rpc url - if (!rpc_url.startsWith('wss://') && !rpc_url.startsWith('ws://')) { - alert('Invalid RPC URL'); - return; - } - const body = { - "EthConfig": { - "AddProvider": { - chain_id: Number(data.get('chain-id')), - trusted: false, - provider: { "RpcUrl": rpc_url }, - } - } - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - e.target.reset(); - return; - } else { - alert(data); - } - }); -}) - -document.getElementById('remove-eth-provider').addEventListener('submit', (e) => { - e.preventDefault(); - const data = new FormData(e.target); - const body = { - "EthConfig": { - "RemoveProvider": [Number(data.get('chain-id')), data.get('rpc-url')] - } - }; - fetch(APP_PATH, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(body), - }).then(response => response.json()) - .then(data => { - if (data === null) { - e.target.reset(); - return; - } else { - alert(data); - } - }); -}) - // Setup WebSocket connection -const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; -const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/"); -ws.onmessage = event => { - const data = JSON.parse(event.data); - console.log(data); - populate(data); -}; +// const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; +// const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/"); +// ws.onmessage = event => { +// const data = JSON.parse(event.data); +// console.log(data); +// populate(data); +// }; From 4d0e8ff3696df138b888284b3b437e1f786854d2 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Wed, 16 Oct 2024 12:33:58 -0400 Subject: [PATCH 03/13] . --- kinode/packages/contacts/contacts/src/lib.rs | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index b407bd55..e34203f6 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -110,9 +110,10 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ if source.node() != state.our.node { continue; // ignore messages from other nodes } - let response = handle_request(&source, &body, state, http_server); + let response_and_blob = handle_request(&source, &body, state, http_server); // state.ws_update(http_server); - if expects_response.is_some() { + if expects_response.is_some() && response_and_blob.is_some() { + let (response, blob) = response_and_blob.unwrap(); Response::new() .body(serde_json::to_vec(&response).unwrap()) .send() @@ -171,15 +172,14 @@ fn handle_http_request( "POST" => { let blob = get_blob().unwrap(); let request = serde_json::from_slice::(&blob.bytes).unwrap(); - let response = handle_contacts_request(state, request); - let response: Option = Some("ok".to_string()); + let (_response, blob) = handle_contacts_request(state, request); ( http::server::HttpResponse::new(http::StatusCode::OK) .header("Content-Type", "application/json"), - match response { - Some(data) => Some(LazyLoadBlob::new( + match blob { + Some(blob) => Some(LazyLoadBlob::new( Some("application/json"), - serde_json::to_vec(&data).unwrap(), + serde_json::to_vec(&blob.bytes).unwrap(), )), None => None, }, @@ -196,8 +196,8 @@ fn handle_http_request( fn handle_contacts_request( state: &mut ContactsState, request: ContactsRequest, -) -> ContactsResponse { - match request { +) -> (ContactsResponse, Option) { + let response = match request { ContactsRequest::GetNames => ContactsResponse::GetNames( state .contacts() @@ -212,5 +212,6 @@ fn handle_contacts_request( ContactsRequest::AddField((node, field, value)) => ContactsResponse::AddField, ContactsRequest::RemoveContact(node) => ContactsResponse::RemoveContact, ContactsRequest::RemoveField((node, field)) => ContactsResponse::RemoveField, - } + }; + (response, None) } From c2cce9d3764f455b820c886e01e520e861f29e00 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Wed, 16 Oct 2024 17:10:03 -0400 Subject: [PATCH 04/13] contacts FE --- Cargo.lock | 26 ++- README.md | 1 + kinode/packages/contacts/Cargo.lock | 5 +- .../packages/contacts/api/contacts:sys-v0.wit | 1 + kinode/packages/contacts/contacts/Cargo.toml | 2 +- kinode/packages/contacts/contacts/src/icon | 2 +- kinode/packages/contacts/contacts/src/lib.rs | 184 +++++++++++++----- kinode/packages/contacts/pkg/manifest.json | 2 + kinode/packages/contacts/pkg/ui/index.html | 12 ++ kinode/packages/contacts/pkg/ui/script.js | 63 ++++-- kinode/packages/settings/Cargo.lock | 5 +- kinode/packages/settings/settings/Cargo.toml | 2 +- 12 files changed, 229 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01749e34..cea58e23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1867,7 +1867,7 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" name = "contacts" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.3", + "kinode_process_lib 0.9.4", "serde", "serde_json", "wit-bindgen", @@ -3759,6 +3759,28 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "kinode_process_lib" +version = "0.9.4" +source = "git+https://github.com/kinode-dao/process_lib?rev=088a549#088a5497257eada697e0869d6a8d7e9ef5e620f6" +dependencies = [ + "alloy 0.1.4", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "bincode", + "http 1.1.0", + "mime_guess", + "rand 0.8.5", + "rmp-serde", + "serde", + "serde_json", + "thiserror", + "url", + "wit-bindgen", +] + [[package]] name = "kit" version = "0.7.7" @@ -5580,7 +5602,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bincode", - "kinode_process_lib 0.9.3", + "kinode_process_lib 0.9.4", "rmp-serde", "serde", "serde_json", diff --git a/README.md b/README.md index c86f767b..d4b1fc2b 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ The distro userspace packages are: - `app_store:sys` - `chess:sys` +- `contacts:sys` - `homepage:sys` - `kino_updates:sys` - `kns_indexer:sys` diff --git a/kinode/packages/contacts/Cargo.lock b/kinode/packages/contacts/Cargo.lock index ad63c9ae..9df40bfb 100644 --- a/kinode/packages/contacts/Cargo.lock +++ b/kinode/packages/contacts/Cargo.lock @@ -1462,9 +1462,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7722aef4bff0625445fafda89a02f82ce0e16c7def6024e1317ae55a632ad331" +version = "0.9.4" +source = "git+https://github.com/kinode-dao/process_lib?rev=088a549#088a5497257eada697e0869d6a8d7e9ef5e620f6" dependencies = [ "alloy", "alloy-primitives", diff --git a/kinode/packages/contacts/api/contacts:sys-v0.wit b/kinode/packages/contacts/api/contacts:sys-v0.wit index a689775b..a567bf26 100644 --- a/kinode/packages/contacts/api/contacts:sys-v0.wit +++ b/kinode/packages/contacts/api/contacts:sys-v0.wit @@ -26,6 +26,7 @@ interface contacts { add-field, remove-contact, remove-field, + error(string), } } diff --git a/kinode/packages/contacts/contacts/Cargo.toml b/kinode/packages/contacts/contacts/Cargo.toml index 54c6bada..b848209f 100644 --- a/kinode/packages/contacts/contacts/Cargo.toml +++ b/kinode/packages/contacts/contacts/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = "0.9.3" +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "088a549" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/contacts/contacts/src/icon b/kinode/packages/contacts/contacts/src/icon index d5143fe3..f67b371b 100644 --- a/kinode/packages/contacts/contacts/src/icon +++ b/kinode/packages/contacts/contacts/src/icon @@ -1 +1 @@ -data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM2IiBoZWlnaHQ9IjEzNiIgdmlld0JveD0iMCAwIDEzNiAxMzYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMzYiIGhlaWdodD0iMTM2IiByeD0iNjgiIGZpbGw9IiNGRkY1RDkiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xODIxXzkwOTMpIj4KPHBhdGggZD0iTTY3LjQ4NTUgOTQuOTg4MUM2NS44MTYxIDk0Ljk4ODEgNjQuMTQ2NyA5NC45NjQzIDYyLjQ3NzIgOTQuOTg4MUM2MS41NjAyIDk1LjAxMTkgNjEuMDQyOSA5NC40MTc0IDYwLjkzNzEgOTMuNjQ0N0M2MC42NjY3IDkxLjU1MjMgNjAuMzQ5MyA4OS40NTk4IDYwLjA2NzEgODcuMzY3NEM2MC4wMjAxIDg3LjAxMDggNTkuODc5IDg2Ljc5NjggNTkuNTM4MSA4Ni42NTQxQzU4LjIzMzEgODYuMDgzNCA1Ny4wMjIyIDg1LjM1ODIgNTUuODgxOCA4NC40OTA0QzU1LjYyMzEgODQuMjg4MiA1NS4zOTk4IDg0LjI2NDUgNTUuMDk0MSA4NC4zOTUyQzUzLjE1NDMgODUuMjAzNyA1MS4yMTQ0IDg1Ljk4ODMgNDkuMjc0NiA4Ni43NzNDNDguMjc1MyA4Ny4xNzcyIDQ3Ljc5MzMgODcuMDIyNyA0Ny4yNTI1IDg2LjA5NTNDNDUuNTcxMyA4My4xNTg4IDQzLjg5MDEgODAuMjEwNCA0Mi4yMDg5IDc3LjI2MkM0MS44MDkyIDc2LjU3MjUgNDEuOTI2NyA3NS45NDIzIDQyLjU0OTggNzUuNDQzQzQ0LjIzMSA3NC4wOTk2IDQ1LjkxMjIgNzIuNzU2MiA0Ny42MDUyIDcxLjQzNjVDNDcuODk5MSA3MS4yMTA2IDQ4LjAwNDkgNzAuOTYxIDQ3Ljk1NzkgNzAuNTkyNEM0Ny43ODE1IDY5LjIwMTQgNDcuNzkzMyA2Ny43OTg2IDQ3Ljk1NzkgNjYuNDA3NkM0OC4wMDQ5IDY2LjA1MDkgNDcuOTEwOCA2NS44MTMxIDQ3LjYyODcgNjUuNTg3M0M0NS45OTQ1IDY0LjMwMzMgNDQuMzYwNCA2My4wMDc0IDQyLjczNzkgNjEuNzExNUM0MS44Nzk3IDYxLjAzMzkgNDEuNzczOSA2MC41MTA4IDQyLjMxNDcgNTkuNTcxNkM0NC4wMDc3IDU2LjYxMTMgNDUuNjg4OCA1My42MzkxIDQ3LjM5MzYgNTAuNjc4OEM0Ny43NDYyIDUwLjA3MjUgNDguMzgxMSA0OS44NTg1IDQ5LjA3NDcgNTAuMTQzOEM1MC40MjY3IDUwLjY5MDcgNTEuNzc4OCA1MS4yMzc1IDUzLjEzMDggNTEuNzk2M0M1My44MjQ0IDUyLjA4MTcgNTQuNTE4IDUyLjM1NTEgNTUuMjExNyA1Mi42NTIzQzU1LjQyMzMgNTIuNzQ3NCA1NS41ODc5IDUyLjczNTUgNTUuNzc2IDUyLjU5MjlDNTYuOTg2OSA1MS42NjU1IDU4LjMwMzYgNTAuODkyOCA1OS43MDI3IDUwLjI4NjVDNTkuOTQ5NiA1MC4xNzk1IDYwLjAyMDEgNDkuOTg5MiA2MC4wNDM2IDQ5Ljc1MTVDNjAuMzE0IDQ3LjgxMzYgNjAuNTg0NCA0NS44NzU3IDYwLjg1NDggNDMuOTM3OUM2MC44OTAxIDQzLjcxMiA2MC45MTM2IDQzLjQ4NjEgNjAuOTQ4OSA0My4yNjAyQzYxLjA5IDQyLjQxNjEgNjEuNTYwMiA0MiA2Mi4zNzE0IDQyQzY0LjQ0MDYgNDIgNjYuNTA5NyA0MiA2OC41Nzg5IDQyQzY5LjkwNzQgNDIgNzEuMjQ3NiA0MiA3Mi41NzYxIDQyQzczLjQ0NjEgNDIgNzMuOTI4MSA0Mi40NTE4IDc0LjA1NzUgNDMuMzMxNUM3NC4zNTE0IDQ1LjQzNTggNzQuNjQ1MyA0Ny41NDAyIDc0LjkyNzQgNDkuNjQ0NUM3NC45NzQ1IDQ5Ljk4OTIgNzUuMTE1NSA1MC4xNzk1IDc1LjQzMyA1MC4zMzRDNzYuNzM4IDUwLjkxNjYgNzcuOTcyNCA1MS42Mjk5IDc5LjExMjggNTIuNTA5NkM3OS4zNTk3IDUyLjY5OTkgNzkuNTU5NSA1Mi43MjM2IDc5Ljg0MTcgNTIuNjA0OEM4MS44MDUgNTEuNzk2MyA4My43Njg0IDUwLjk4NzkgODUuNzQzNSA1MC4xOTEzQzg2LjY3MjMgNDkuODEwOSA4Ny4yMTMxIDUwLjAxMyA4Ny43MTg2IDUwLjg5MjhDODkuMzc2MyA1My44MDU1IDkxLjAzMzkgNTYuNzE4MyA5Mi42OTE2IDU5LjYxOTFDOTMuMTczNiA2MC40NTEzIDkzLjA2NzggNjEuMDIyIDkyLjMxNTQgNjEuNjI4M0M5MC42NDYgNjIuOTU5OCA4OC45NzY1IDY0LjI3OTUgODcuMjk1NCA2NS41ODczQzg3LjAyNDkgNjUuODAxMyA4Ni45NDI3IDY2LjAyNzEgODYuOTc3OSA2Ni4zNkM4Ny4xNTQzIDY3Ljc4NjcgODcuMTU0MyA2OS4yMTMzIDg2Ljk3NzkgNzAuNjRDODYuOTQyNyA3MC45NjEgODcuMDI1IDcxLjE4NjkgODcuMjgzNiA3MS4zODlDODguOTI5NSA3Mi42ODQ4IDkwLjU3NTQgNzMuOTkyNiA5Mi4yMjE0IDc1LjMwMDRDOTMuMDU2MSA3NS45NjYxIDkzLjE2MTkgNzYuNDg5MiA5Mi42MzI4IDc3LjQxNjZDOTAuOTc1MiA4MC4zNDEyIDg5LjMwNTcgODMuMjUzOSA4Ny42MzYzIDg2LjE2NjdDODcuMTg5NSA4Ni45NTEzIDg2LjYwMTcgODcuMTUzNCA4NS43NjcgODYuODA4N0M4My44MDM3IDg2LjAxMjEgODEuODUyMSA4NS4yMTU2IDc5LjkwMDUgODQuNDA3MUM3OS41NzEzIDg0LjI2NDUgNzkuMzI0NCA4NC4yODgyIDc5LjAzMDUgODQuNTE0MUM3Ny45MDE5IDg1LjM5MzkgNzYuNjc5MiA4Ni4wOTUzIDc1LjM3NDIgODYuNjY2Qzc1LjA2ODUgODYuNzk2OCA3NC45MzkyIDg2Ljk4NyA3NC44OTIyIDg3LjMwOEM3NC42MSA4OS40MDA0IDc0LjMxNjEgOTEuNDkyOCA3NC4wMTA0IDkzLjU4NTJDNzMuOTYzNCA5My45MDYyIDczLjgzNDEgOTQuMjI3MiA3My42Njk1IDk0LjUwMDdDNzMuNDM0NCA5NC44NTczIDczLjA1ODEgOTQuOTg4MSA3Mi42MjMxIDk0Ljk4ODFDNzAuOTA2NyA5NC45ODgxIDY5LjE3ODUgOTQuOTg4MSA2Ny40NjIgOTQuOTg4MUg2Ny40ODU1Wk02Ny40NzM4IDU5LjE1NTVDNjIuNDMwMiA1OS4xNTU1IDU4LjI2ODQgNjMuMzUyMiA1OC4yNTY2IDY4LjQ2NDNDNTguMjQ0OSA3My42MDAzIDYyLjQwNjcgNzcuODIwOCA2Ny40ODU1IDc3LjgyMDhDNzIuNTUyNiA3Ny44MjA4IDc2LjcxNDQgNzMuNjEyMiA3Ni43MTQ0IDY4LjQ4ODFDNzYuNzE0NCA2My4zNDAzIDcyLjU2NDQgNTkuMTU1NSA2Ny40NjIgNTkuMTQzNkw2Ny40NzM4IDU5LjE1NTVaIiBmaWxsPSIjRkZGNUQ5Ii8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMTgyMV85MDkzIj4KPHJlY3Qgd2lkdGg9IjUxIiBoZWlnaHQ9IjUzIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDIgNDIpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg== \ No newline at end of file +data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwMCIgaGVpZ2h0PSIxMDAwIiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cmVjdCB4PSIyMCIgeT0iMjAiIHdpZHRoPSI5NjAiIGhlaWdodD0iOTYwIiByeD0iNDgwIiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXJfMjA5MV8xMDI4MikiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CjxyZWN0IHg9IjIwIiB5PSIyMCIgd2lkdGg9Ijk2MCIgaGVpZ2h0PSI5NjAiIHJ4PSI0ODAiIHN0cm9rZT0idXJsKCNwYWludDFfbGluZWFyXzIwOTFfMTAyODIpIiBzdHJva2Utd2lkdGg9IjQwIi8+CjxwYXRoIGQ9Ik01ODEuMTE2IDU4NS43ODNMNjY0LjUzOCA2NjkuMTJDNjE3LjY5OSA3MTUuNzU4IDU1Ni42MjUgNzM5IDQ5NS4yNDUgNzM5QzQzMy44NjUgNzM5IDM3Mi42MzggNzE1LjYwNSAzMjYuMTA1IDY2OS4xMkMyODAuNzk3IDYyMy44NTggMjU2IDU2My45MTcgMjU2IDUwMEMyNTYgNDM2LjA4MyAyODAuOTUgMzc2LjE0MiAzMjYuMTA1IDMzMC44OEMzNzEuMjYgMjg1LjYxOSA0MzEuMjYyIDI2MSA0OTUuMjQ1IDI2MUM1NTkuMjI3IDI2MSA2MTkuMjMgMjg1LjkyNCA2NjQuNTM4IDMzMC44OEw1ODAuOTYzIDQxNC41MjNDNTQ1LjYwNCAzODMuOTQgNTA1LjE5NCAzNzQuNzY2IDQ2MS4yNjQgMzkxLjEyN0MzOTQuOTg1IDQxNS44OTkgMzY2LjgyMSA0ODkuMjk2IDM5Ny40MzUgNTUyLjc1NEMzOTguNjU5IDU1NS4yMDEgMzk4Ljk2NSA1NTguNzE4IDM5OC4zNTMgNTYxLjMxN0MzOTUuNzUxIDU3Mi40OCAzOTIuNjg5IDU4My40OSAzODkuNzgxIDU5NC4zNDZDMzg2LjEwNyA2MDcuOTU1IDM5My45MTQgNjE1Ljc1NCA0MDcuNTM3IDYxMi4yMzdDNDE4LjU1OCA2MDkuMzMxIDQyOS41NzkgNjA2LjEyIDQ0MC42IDYwMy42NzRDNDQzLjM1NSA2MDIuOTA5IDQ0Ny4wMjkgNjAzLjIxNSA0NDkuNjMxIDYwNC40MzhDNDkwLjUgNjIzLjM5OSA1MjkuOTkxIDYyMC44IDU2Ny43OTkgNTk2LjE4MUM1NzIuNTQ0IDU5My4xMjMgNTc2LjY3NyA1ODkuNDUzIDU4MS4xMTYgNTg1Ljc4M1oiIGZpbGw9InVybCgjcGFpbnQyX2xpbmVhcl8yMDkxXzEwMjgyKSIvPgo8ZGVmcz4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzIwOTFfMTAyODIiIHgxPSI1MDAiIHkxPSIwIiB4Mj0iNTAwIiB5Mj0iMTAwMCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1vcGFjaXR5PSIwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl8yMDkxXzEwMjgyIiB4MT0iNzgyLjUiIHkxPSI3My41IiB4Mj0iMTg1LjUiIHkyPSI4OTQuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRjM1NDIyIi8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0E1MzEwQyIvPgo8L2xpbmVhckdyYWRpZW50Pgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50Ml9saW5lYXJfMjA5MV8xMDI4MiIgeDE9Ijc1NCIgeTE9Ijg5LjUiIHgyPSIyNTYiIHkyPSIxMDE1LjUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0YzNTQyMiIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNBNzMyMEQiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K \ No newline at end of file diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index e34203f6..25a72e7d 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -1,7 +1,7 @@ use crate::kinode::process::contacts::{ContactsRequest, ContactsResponse}; use kinode_process_lib::{ - await_message, call_init, get_blob, get_typed_state, homepage, http, println, set_state, - Address, LazyLoadBlob, Message, NodeId, Response, + await_message, call_init, eth, get_blob, get_typed_state, homepage, http, kimap, kiprintln, + set_state, Address, LazyLoadBlob, Message, NodeId, Response, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -17,6 +17,7 @@ struct Contacts(HashMap); #[derive(Debug, Serialize, Deserialize)] struct ContactsState { our: Address, + kimap: kimap::Kimap, contacts: Contacts, } @@ -24,6 +25,7 @@ impl ContactsState { fn new(our: Address) -> Self { get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self { our, + kimap: kimap::Kimap::default(30), contacts: Contacts(HashMap::new()), }) } @@ -42,10 +44,12 @@ impl ContactsState { fn add_contact(&mut self, node: NodeId) { self.contacts.0.insert(node, Contact(HashMap::new())); + self.save(); } fn remove_contact(&mut self, node: NodeId) { self.contacts.0.remove(&node); + self.save(); } fn add_field(&mut self, node: NodeId, field: String, value: serde_json::Value) { @@ -55,12 +59,25 @@ impl ContactsState { .or_insert_with(|| Contact(HashMap::new())) .0 .insert(field, value); + self.save(); } fn remove_field(&mut self, node: NodeId, field: String) { if let Some(contact) = self.contacts.0.get_mut(&node) { contact.0.remove(&field); } + self.save(); + } + + fn ws_update(&self, http_server: &mut http::server::HttpServer) { + http_server.ws_push_all_channels( + "/", + http::server::WsMessageType::Text, + LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(self.contacts()).unwrap(), + ), + ); } } @@ -73,6 +90,8 @@ wit_bindgen::generate!({ call_init!(initialize); fn initialize(our: Address) { + kiprintln!("started"); + homepage::add_to_homepage("Contacts", Some(ICON), Some("/"), None); let mut state: ContactsState = ContactsState::new(our); @@ -101,24 +120,13 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ // ignore send errors, local-only process continue; } - Ok(Message::Request { - source, - body, - expects_response, - .. - }) => { + Ok(Message::Request { source, body, .. }) => { + // ignore messages from other nodes -- technically superfluous check + // since manifest does not acquire networking capability if source.node() != state.our.node { - continue; // ignore messages from other nodes - } - let response_and_blob = handle_request(&source, &body, state, http_server); - // state.ws_update(http_server); - if expects_response.is_some() && response_and_blob.is_some() { - let (response, blob) = response_and_blob.unwrap(); - Response::new() - .body(serde_json::to_vec(&response).unwrap()) - .send() - .unwrap(); + continue; } + handle_request(&source, &body, state, http_server); } _ => continue, // ignore responses } @@ -130,7 +138,7 @@ fn handle_request( body: &[u8], state: &mut ContactsState, http_server: &mut http::server::HttpServer, -) -> Option { +) { // source node is ALWAYS ourselves since networking is disabled if source.process == "http_server:distro:sys" { // receive HTTP requests and websocket connection messages from our server @@ -143,13 +151,15 @@ fn handle_request( // we don't expect websocket messages }, ); - None } else { - // let settings_request = serde_json::from_slice::(body) - // .map_err(|_| SettingsError::MalformedRequest)?; - // handle_settings_request(state, settings_request) - None + let (response, blob) = handle_contacts_request(state, body); + let mut response = Response::new().body(serde_json::to_vec(&response).unwrap()); + if let Some(blob) = blob { + response = response.blob(blob); + } + response.send().unwrap(); } + state.ws_update(http_server); } /// Handle HTTP requests from our own frontend. @@ -158,21 +168,27 @@ fn handle_http_request( http_request: &http::server::IncomingHttpRequest, ) -> (http::server::HttpResponse, Option) { match http_request.method().unwrap().as_str() { - "GET" => { - // state.fetch().unwrap(); - ( - http::server::HttpResponse::new(http::StatusCode::OK) - .header("Content-Type", "application/json"), - Some(LazyLoadBlob::new( - Some("application/json"), - serde_json::to_vec(&state).unwrap(), - )), - ) - } + "GET" => ( + http::server::HttpResponse::new(http::StatusCode::OK) + .header("Content-Type", "application/json"), + Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(state.contacts()).unwrap(), + )), + ), "POST" => { let blob = get_blob().unwrap(); - let request = serde_json::from_slice::(&blob.bytes).unwrap(); - let (_response, blob) = handle_contacts_request(state, request); + let (response, blob) = handle_contacts_request(state, blob.bytes()); + if let ContactsResponse::Error(e) = response { + return ( + http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST) + .header("Content-Type", "application/json"), + Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(&e).unwrap(), + )), + ); + } ( http::server::HttpResponse::new(http::StatusCode::OK) .header("Content-Type", "application/json"), @@ -195,23 +211,83 @@ fn handle_http_request( fn handle_contacts_request( state: &mut ContactsState, - request: ContactsRequest, + request_bytes: &[u8], ) -> (ContactsResponse, Option) { - let response = match request { - ContactsRequest::GetNames => ContactsResponse::GetNames( - state - .contacts() - .0 - .keys() - .map(|node| node.to_string()) - .collect(), - ), - ContactsRequest::GetAllContacts => ContactsResponse::GetAllContacts, - ContactsRequest::GetContact(node) => ContactsResponse::GetContact, - ContactsRequest::AddContact(node) => ContactsResponse::AddContact, - ContactsRequest::AddField((node, field, value)) => ContactsResponse::AddField, - ContactsRequest::RemoveContact(node) => ContactsResponse::RemoveContact, - ContactsRequest::RemoveField((node, field)) => ContactsResponse::RemoveField, + let Ok(request) = serde_json::from_slice::(request_bytes) else { + return ( + ContactsResponse::Error("Malformed request".to_string()), + None, + ); }; - (response, None) + match request { + ContactsRequest::GetNames => ( + ContactsResponse::GetNames( + state + .contacts() + .0 + .keys() + .map(|node| node.to_string()) + .collect(), + ), + None, + ), + ContactsRequest::GetAllContacts => ( + ContactsResponse::GetAllContacts, + Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(state.contacts()).unwrap(), + )), + ), + ContactsRequest::GetContact(node) => ( + ContactsResponse::GetContact, + Some(LazyLoadBlob::new( + Some("application/json"), + serde_json::to_vec(&state.get_contact(node)).unwrap(), + )), + ), + ContactsRequest::AddContact(node) => { + if let Some((response, blob)) = invalid_node(state, &node) { + return (response, blob); + } + state.add_contact(node); + (ContactsResponse::AddContact, None) + } + ContactsRequest::AddField((node, field, value)) => { + if let Some((response, blob)) = invalid_node(state, &node) { + return (response, blob); + } + let Ok(value) = serde_json::from_str::(&value) else { + return (ContactsResponse::Error("Malformed value".to_string()), None); + }; + state.add_field(node, field, value); + (ContactsResponse::AddField, None) + } + ContactsRequest::RemoveContact(node) => { + state.remove_contact(node); + (ContactsResponse::RemoveContact, None) + } + ContactsRequest::RemoveField((node, field)) => { + state.remove_field(node, field); + (ContactsResponse::RemoveField, None) + } + } +} + +fn invalid_node( + state: &ContactsState, + node: &str, +) -> Option<(ContactsResponse, Option)> { + if state + .kimap + .get(&node) + .map(|(tba, _, _)| tba != eth::Address::ZERO) + .unwrap_or(false) + { + None + } else { + Some(( + ContactsResponse::Error("Node name invalid or does not exist".to_string()), + None, + )) + } } diff --git a/kinode/packages/contacts/pkg/manifest.json b/kinode/packages/contacts/pkg/manifest.json index 4d28b723..03dd9b26 100644 --- a/kinode/packages/contacts/pkg/manifest.json +++ b/kinode/packages/contacts/pkg/manifest.json @@ -5,11 +5,13 @@ "on_exit": "Restart", "request_networking": false, "request_capabilities": [ + "eth:distro:sys", "homepage:homepage:sys", "http_server:distro:sys", "vfs:distro:sys" ], "grant_capabilities": [ + "eth:distro:sys", "http_server:distro:sys", "vfs:distro:sys" ], diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html index e6dcb5ad..bad57611 100644 --- a/kinode/packages/contacts/pkg/ui/index.html +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -47,6 +47,18 @@

                  contacts

                  +
                  +

                  Contacts

                  +
                  + + +
                  +
                  + +
                  +
                    +
                    +
                    diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index 8f1376c5..830ffe14 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -1,16 +1,16 @@ -const APP_PATH = '/contacts:contacts:sys/'; +const APP_PATH = '/contacts:contacts:sys/ask'; // Fetch initial data and populate the UI function init() { - fetch(APP_PATH + 'get') + fetch(APP_PATH) .then(response => response.json()) .then(data => { populate(data); }); } -function api_call(path, body) { - fetch(APP_PATH + path, { +function api_call(body) { + fetch(APP_PATH, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -21,17 +21,58 @@ function api_call(path, body) { function populate(data) { console.log(data); + populate_contacts(data); } +function populate_contacts(contacts) { + const ul = document.getElementById('contacts'); + ul.innerHTML = ''; + Object.entries(contacts).forEach(([node, contact]) => { + const li = document.createElement('li'); + li.innerHTML = `${JSON.stringify(node, undefined, 2)}`; + ul.appendChild(li); + }); +} + +document.getElementById('add-contact').addEventListener('submit', (e) => { + e.preventDefault(); + const data = new FormData(e.target); + const node = data.get('node'); + const body = { + "AddContact": node + }; + fetch(APP_PATH, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }).then(response => { + if (response.status === 200) { + return null; + } else { + return response.json(); + } + }).then(data => { + if (data === null) { + e.target.reset(); + return; + } else { + alert(JSON.stringify(data)); + } + }).catch(error => { + console.error('Error:', error); + }); +}) + // Call init to start the application init(); // Setup WebSocket connection -// const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; -// const ws = new WebSocket(wsProtocol + location.host + "/settings:settings:sys/"); -// ws.onmessage = event => { -// const data = JSON.parse(event.data); -// console.log(data); -// populate(data); -// }; +const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; +const ws = new WebSocket(wsProtocol + location.host + "/contacts:contacts:sys/"); +ws.onmessage = event => { + const data = JSON.parse(event.data); + populate(data); +}; diff --git a/kinode/packages/settings/Cargo.lock b/kinode/packages/settings/Cargo.lock index 8c57f800..93b2abe5 100644 --- a/kinode/packages/settings/Cargo.lock +++ b/kinode/packages/settings/Cargo.lock @@ -1452,9 +1452,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c5b69ac1fc0cb457c7714ceb8c0a5bdbee4ee00b837f9f16ea711e902bdfe8" +version = "0.9.4" +source = "git+https://github.com/kinode-dao/process_lib?rev=088a549#088a5497257eada697e0869d6a8d7e9ef5e620f6" dependencies = [ "alloy", "alloy-primitives", diff --git a/kinode/packages/settings/settings/Cargo.toml b/kinode/packages/settings/settings/Cargo.toml index b3bfdb8d..83ad7e7f 100644 --- a/kinode/packages/settings/settings/Cargo.toml +++ b/kinode/packages/settings/settings/Cargo.toml @@ -10,7 +10,7 @@ simulation-mode = [] anyhow = "1.0" base64 = "0.22.0" bincode = "1.3.3" -kinode_process_lib = "0.9.1" +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "088a549" } rmp-serde = "1.2.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" From 8056ccb16ca743bb070639c25b825ceb1e888142 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Wed, 16 Oct 2024 17:12:12 -0400 Subject: [PATCH 05/13] remove init, ws handles it --- kinode/packages/contacts/pkg/ui/script.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index 830ffe14..67b3cac0 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -1,14 +1,5 @@ const APP_PATH = '/contacts:contacts:sys/ask'; -// Fetch initial data and populate the UI -function init() { - fetch(APP_PATH) - .then(response => response.json()) - .then(data => { - populate(data); - }); -} - function api_call(body) { fetch(APP_PATH, { method: 'POST', @@ -65,9 +56,6 @@ document.getElementById('add-contact').addEventListener('submit', (e) => { }); }) -// Call init to start the application -init(); - // Setup WebSocket connection const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; const ws = new WebSocket(wsProtocol + location.host + "/contacts:contacts:sys/"); From 47527976e552ff307f291d1b533ae0a80515f185 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Thu, 17 Oct 2024 15:14:34 -0400 Subject: [PATCH 06/13] add capabilities checks, refactor API --- .../packages/contacts/api/contacts:sys-v0.wit | 8 +- kinode/packages/contacts/contacts/src/lib.rs | 92 +++++++++++++------ kinode/packages/terminal/pkg/manifest.json | 2 + 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/kinode/packages/contacts/api/contacts:sys-v0.wit b/kinode/packages/contacts/api/contacts:sys-v0.wit index a567bf26..37022f1e 100644 --- a/kinode/packages/contacts/api/contacts:sys-v0.wit +++ b/kinode/packages/contacts/api/contacts:sys-v0.wit @@ -6,7 +6,7 @@ interface contacts { remove, } - variant contacts-request { + variant request { get-names, // requires read-names-only get-all-contacts, // requires read get-contact(string), // requires read @@ -18,15 +18,15 @@ interface contacts { remove-field(tuple), // requires remove } - variant contacts-response { + variant response { get-names(list), get-all-contacts, // JSON all-contacts dict in blob - get-contact, // JSON contact dict in blob + get-contact, // JSON contact dict in blob add-contact, add-field, remove-contact, remove-field, - error(string), + error(string), // any failed request will receive this response } } diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index 25a72e7d..35463455 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -1,7 +1,7 @@ -use crate::kinode::process::contacts::{ContactsRequest, ContactsResponse}; +use crate::kinode::process::contacts; use kinode_process_lib::{ await_message, call_init, eth, get_blob, get_typed_state, homepage, http, kimap, kiprintln, - set_state, Address, LazyLoadBlob, Message, NodeId, Response, + set_state, Address, Capability, LazyLoadBlob, Message, NodeId, Response, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -120,13 +120,18 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ // ignore send errors, local-only process continue; } - Ok(Message::Request { source, body, .. }) => { + Ok(Message::Request { + source, + body, + capabilities, + .. + }) => { // ignore messages from other nodes -- technically superfluous check // since manifest does not acquire networking capability if source.node() != state.our.node { continue; } - handle_request(&source, &body, state, http_server); + handle_request(&source, &body, capabilities, state, http_server); } _ => continue, // ignore responses } @@ -136,6 +141,7 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ fn handle_request( source: &Address, body: &[u8], + capabilities: Vec, state: &mut ContactsState, http_server: &mut http::server::HttpServer, ) { @@ -152,7 +158,8 @@ fn handle_request( }, ); } else { - let (response, blob) = handle_contacts_request(state, body); + // if request is not from frontend, check that it has the required capabilities + let (response, blob) = handle_contacts_request(state, body, Some(capabilities)); let mut response = Response::new().body(serde_json::to_vec(&response).unwrap()); if let Some(blob) = blob { response = response.blob(blob); @@ -178,8 +185,8 @@ fn handle_http_request( ), "POST" => { let blob = get_blob().unwrap(); - let (response, blob) = handle_contacts_request(state, blob.bytes()); - if let ContactsResponse::Error(e) = response { + let (response, blob) = handle_contacts_request(state, blob.bytes(), None); + if let contacts::Response::Error(e) = response { return ( http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST) .header("Content-Type", "application/json"), @@ -212,16 +219,44 @@ fn handle_http_request( fn handle_contacts_request( state: &mut ContactsState, request_bytes: &[u8], -) -> (ContactsResponse, Option) { - let Ok(request) = serde_json::from_slice::(request_bytes) else { + capabilities: Option>, +) -> (contacts::Response, Option) { + let Ok(request) = serde_json::from_slice::(request_bytes) else { return ( - ContactsResponse::Error("Malformed request".to_string()), + contacts::Response::Error("Malformed request".to_string()), None, ); }; + // if request is not from frontend, check capabilities: + // each request requires one of read-name-only, read, add, or remove + if let Some(capabilities) = capabilities { + let required_capability = Capability::new( + &state.our, + serde_json::to_string(&match request { + contacts::Request::GetNames => contacts::Capabilities::ReadNameOnly, + contacts::Request::GetAllContacts | contacts::Request::GetContact(_) => { + contacts::Capabilities::Read + } + contacts::Request::AddContact(_) | contacts::Request::AddField(_) => { + contacts::Capabilities::Add + } + contacts::Request::RemoveContact(_) | contacts::Request::RemoveField(_) => { + contacts::Capabilities::Remove + } + }) + .unwrap(), + ); + if !capabilities.contains(&required_capability) { + return ( + contacts::Response::Error("Missing capability".to_string()), + None, + ); + } + } + match request { - ContactsRequest::GetNames => ( - ContactsResponse::GetNames( + contacts::Request::GetNames => ( + contacts::Response::GetNames( state .contacts() .0 @@ -231,44 +266,47 @@ fn handle_contacts_request( ), None, ), - ContactsRequest::GetAllContacts => ( - ContactsResponse::GetAllContacts, + contacts::Request::GetAllContacts => ( + contacts::Response::GetAllContacts, Some(LazyLoadBlob::new( Some("application/json"), serde_json::to_vec(state.contacts()).unwrap(), )), ), - ContactsRequest::GetContact(node) => ( - ContactsResponse::GetContact, + contacts::Request::GetContact(node) => ( + contacts::Response::GetContact, Some(LazyLoadBlob::new( Some("application/json"), serde_json::to_vec(&state.get_contact(node)).unwrap(), )), ), - ContactsRequest::AddContact(node) => { + contacts::Request::AddContact(node) => { if let Some((response, blob)) = invalid_node(state, &node) { return (response, blob); } state.add_contact(node); - (ContactsResponse::AddContact, None) + (contacts::Response::AddContact, None) } - ContactsRequest::AddField((node, field, value)) => { + contacts::Request::AddField((node, field, value)) => { if let Some((response, blob)) = invalid_node(state, &node) { return (response, blob); } let Ok(value) = serde_json::from_str::(&value) else { - return (ContactsResponse::Error("Malformed value".to_string()), None); + return ( + contacts::Response::Error("Malformed value".to_string()), + None, + ); }; state.add_field(node, field, value); - (ContactsResponse::AddField, None) + (contacts::Response::AddField, None) } - ContactsRequest::RemoveContact(node) => { + contacts::Request::RemoveContact(node) => { state.remove_contact(node); - (ContactsResponse::RemoveContact, None) + (contacts::Response::RemoveContact, None) } - ContactsRequest::RemoveField((node, field)) => { + contacts::Request::RemoveField((node, field)) => { state.remove_field(node, field); - (ContactsResponse::RemoveField, None) + (contacts::Response::RemoveField, None) } } } @@ -276,7 +314,7 @@ fn handle_contacts_request( fn invalid_node( state: &ContactsState, node: &str, -) -> Option<(ContactsResponse, Option)> { +) -> Option<(contacts::Response, Option)> { if state .kimap .get(&node) @@ -286,7 +324,7 @@ fn invalid_node( None } else { Some(( - ContactsResponse::Error("Node name invalid or does not exist".to_string()), + contacts::Response::Error("Node name invalid or does not exist".to_string()), None, )) } diff --git a/kinode/packages/terminal/pkg/manifest.json b/kinode/packages/terminal/pkg/manifest.json index 918314c4..b87e4aaa 100644 --- a/kinode/packages/terminal/pkg/manifest.json +++ b/kinode/packages/terminal/pkg/manifest.json @@ -5,6 +5,8 @@ "on_exit": "Restart", "request_networking": true, "request_capabilities": [ + "app_store:app_store:sys", + "contacts:contacts:sys", "chess:chess:sys", "eth:distro:sys", { From 5ef0771abdc27d768b8089ea9868bc11bfa9f5c4 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Fri, 18 Oct 2024 11:54:22 -0400 Subject: [PATCH 07/13] contacts: present caps in manifest --- kinode/packages/contacts/pkg/manifest.json | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kinode/packages/contacts/pkg/manifest.json b/kinode/packages/contacts/pkg/manifest.json index 03dd9b26..dbc26269 100644 --- a/kinode/packages/contacts/pkg/manifest.json +++ b/kinode/packages/contacts/pkg/manifest.json @@ -13,7 +13,23 @@ "grant_capabilities": [ "eth:distro:sys", "http_server:distro:sys", - "vfs:distro:sys" + "vfs:distro:sys", + { + "process": "main:app_store:sys", + "params": "ReadNameOnly" + }, + { + "process": "main:app_store:sys", + "params": "Read" + }, + { + "process": "main:app_store:sys", + "params": "Add" + }, + { + "process": "main:app_store:sys", + "params": "Remove" + } ], "public": false } From c24d2b51f91888993e3460af39ed7fb666dc51b1 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Fri, 18 Oct 2024 15:42:39 -0400 Subject: [PATCH 08/13] contacts: make kimap work in sim-mode, improve FE --- kinode/packages/contacts/contacts/src/lib.rs | 48 ++++++++++++----- kinode/packages/contacts/pkg/ui/index.html | 55 +++++++++++++++++--- kinode/packages/contacts/pkg/ui/script.js | 40 +++++++++++++- 3 files changed, 122 insertions(+), 21 deletions(-) diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index 35463455..f59f0a73 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -5,9 +5,22 @@ use kinode_process_lib::{ }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +use std::str::FromStr; const ICON: &str = include_str!("icon"); +#[cfg(not(feature = "simulation-mode"))] +const CHAIN_ID: u64 = kimap::KIMAP_CHAIN_ID; +#[cfg(feature = "simulation-mode")] +const CHAIN_ID: u64 = 31337; // local + +const CHAIN_TIMEOUT: u64 = 60; // 60s + +#[cfg(not(feature = "simulation-mode"))] +const KIMAP_ADDRESS: &'static str = kimap::KIMAP_ADDRESS; // optimism +#[cfg(feature = "simulation-mode")] +const KIMAP_ADDRESS: &str = "0xEce71a05B36CA55B895427cD9a440eEF7Cf3669D"; + #[derive(Debug, Serialize, Deserialize)] struct Contact(HashMap); @@ -17,7 +30,6 @@ struct Contacts(HashMap); #[derive(Debug, Serialize, Deserialize)] struct ContactsState { our: Address, - kimap: kimap::Kimap, contacts: Contacts, } @@ -25,7 +37,6 @@ impl ContactsState { fn new(our: Address) -> Self { get_typed_state(|bytes| serde_json::from_slice(bytes)).unwrap_or(Self { our, - kimap: kimap::Kimap::default(30), contacts: Contacts(HashMap::new()), }) } @@ -96,6 +107,11 @@ fn initialize(our: Address) { let mut state: ContactsState = ContactsState::new(our); + let kimap = kimap::Kimap::new( + eth::Provider::new(CHAIN_ID, CHAIN_TIMEOUT), + eth::Address::from_str(KIMAP_ADDRESS).unwrap(), + ); + let mut http_server = http::server::HttpServer::new(5); // serve the frontend on a secure subdomain @@ -110,10 +126,14 @@ fn initialize(our: Address) { http_server.secure_bind_http_path("/ask").unwrap(); http_server.secure_bind_ws_path("/").unwrap(); - main_loop(&mut state, &mut http_server); + main_loop(&mut state, &kimap, &mut http_server); } -fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServer) { +fn main_loop( + state: &mut ContactsState, + kimap: &kimap::Kimap, + http_server: &mut http::server::HttpServer, +) { loop { match await_message() { Err(_send_error) => { @@ -131,7 +151,7 @@ fn main_loop(state: &mut ContactsState, http_server: &mut http::server::HttpServ if source.node() != state.our.node { continue; } - handle_request(&source, &body, capabilities, state, http_server); + handle_request(&source, &body, capabilities, state, kimap, http_server); } _ => continue, // ignore responses } @@ -143,6 +163,7 @@ fn handle_request( body: &[u8], capabilities: Vec, state: &mut ContactsState, + kimap: &kimap::Kimap, http_server: &mut http::server::HttpServer, ) { // source node is ALWAYS ourselves since networking is disabled @@ -152,14 +173,14 @@ fn handle_request( http_server.handle_request( server_request, - |req| handle_http_request(state, &req), + |req| handle_http_request(state, kimap, &req), |_channel_id, _message_type, _blob| { // we don't expect websocket messages }, ); } else { // if request is not from frontend, check that it has the required capabilities - let (response, blob) = handle_contacts_request(state, body, Some(capabilities)); + let (response, blob) = handle_contacts_request(state, kimap, body, Some(capabilities)); let mut response = Response::new().body(serde_json::to_vec(&response).unwrap()); if let Some(blob) = blob { response = response.blob(blob); @@ -172,6 +193,7 @@ fn handle_request( /// Handle HTTP requests from our own frontend. fn handle_http_request( state: &mut ContactsState, + kimap: &kimap::Kimap, http_request: &http::server::IncomingHttpRequest, ) -> (http::server::HttpResponse, Option) { match http_request.method().unwrap().as_str() { @@ -185,7 +207,7 @@ fn handle_http_request( ), "POST" => { let blob = get_blob().unwrap(); - let (response, blob) = handle_contacts_request(state, blob.bytes(), None); + let (response, blob) = handle_contacts_request(state, kimap, blob.bytes(), None); if let contacts::Response::Error(e) = response { return ( http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST) @@ -218,6 +240,7 @@ fn handle_http_request( fn handle_contacts_request( state: &mut ContactsState, + kimap: &kimap::Kimap, request_bytes: &[u8], capabilities: Option>, ) -> (contacts::Response, Option) { @@ -281,14 +304,14 @@ fn handle_contacts_request( )), ), contacts::Request::AddContact(node) => { - if let Some((response, blob)) = invalid_node(state, &node) { + if let Some((response, blob)) = invalid_node(kimap, &node) { return (response, blob); } state.add_contact(node); (contacts::Response::AddContact, None) } contacts::Request::AddField((node, field, value)) => { - if let Some((response, blob)) = invalid_node(state, &node) { + if let Some((response, blob)) = invalid_node(kimap, &node) { return (response, blob); } let Ok(value) = serde_json::from_str::(&value) else { @@ -312,11 +335,10 @@ fn handle_contacts_request( } fn invalid_node( - state: &ContactsState, + kimap: &kimap::Kimap, node: &str, ) -> Option<(contacts::Response, Option)> { - if state - .kimap + if kimap .get(&node) .map(|(tba, _, _)| tba != eth::Address::ZERO) .unwrap_or(false) diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html index bad57611..2f20c2ae 100644 --- a/kinode/packages/contacts/pkg/ui/index.html +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -9,7 +9,7 @@ @@ -48,7 +92,6 @@

                    contacts

                    -

                    Contacts

                    diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index 67b3cac0..03bf4324 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -20,9 +20,45 @@ function populate_contacts(contacts) { ul.innerHTML = ''; Object.entries(contacts).forEach(([node, contact]) => { const li = document.createElement('li'); - li.innerHTML = `${JSON.stringify(node, undefined, 2)}`; + const div = document.createElement('div'); + div.classList.add('contact'); + div.innerHTML = `

                    ${node}

                    +
                      + ${Object.entries(contact).map(([field, value]) => `
                    • ${field}: ${value}
                    • `).join('')} +
                    + + +
                    +
                    + + + +
                    + `; + li.appendChild(div); ul.appendChild(li); }); + + ul.querySelectorAll('.delete-contact').forEach(form => { + form.addEventListener('submit', function (e) { + e.preventDefault(); + const node = this.getAttribute('id'); + api_call({ + "RemoveContact": node + }); + }); + }); + + ul.querySelectorAll('.add-field').forEach(form => { + form.addEventListener('submit', function (e) { + e.preventDefault(); + const node = this.getAttribute('id'); + const data = new FormData(e.target); + api_call({ + "AddField": [node, data.get('field'), data.get('value')] + }); + }); + }); } document.getElementById('add-contact').addEventListener('submit', (e) => { @@ -39,6 +75,7 @@ document.getElementById('add-contact').addEventListener('submit', (e) => { }, body: JSON.stringify(body), }).then(response => { + e.target.reset(); if (response.status === 200) { return null; } else { @@ -46,7 +83,6 @@ document.getElementById('add-contact').addEventListener('submit', (e) => { } }).then(data => { if (data === null) { - e.target.reset(); return; } else { alert(JSON.stringify(data)); From e51c5760d860e2cf9733fbfb9b4894ac14f59f89 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 21 Oct 2024 14:40:32 -0400 Subject: [PATCH 09/13] further improve UI --- kinode/packages/contacts/pkg/ui/index.html | 45 ++++++++++++++++++++-- kinode/packages/contacts/pkg/ui/script.js | 30 +++++++++++++-- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html index 2f20c2ae..934795a6 100644 --- a/kinode/packages/contacts/pkg/ui/index.html +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -24,13 +24,34 @@ font-family: 'Kode Mono', monospace; } - h1 { + #title { + display: flex; + align-items: center; padding: 20px; - max-width: 960px; + max-width: 720px; min-width: 300px; margin: 0 auto; } + #title h1 { + margin: 0; + flex-grow: 1; + text-align: right; + } + + #title button { + margin-right: 20px; + } + + #edit { + max-width: 720px; + margin: 0 auto; + } + + #contacts-article { + margin: 20px; + } + main { margin: 0 auto; padding: 20px; @@ -71,6 +92,8 @@ .contact ul { grid-area: fields; list-style: none; + max-width: 100%; + min-width: 0; } .contact ul li { @@ -85,16 +108,30 @@ grid-area: add-field; max-width: 400px; } + + .remove-field { + background-color: var(--tasteful-red); + font-size: 0.8em; + padding: 3px 10px; + } -

                    contacts

                    + + +

                    contacts

                    +
                    - +
                    diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index 03bf4324..ea1bd94c 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -18,13 +18,19 @@ function populate(data) { function populate_contacts(contacts) { const ul = document.getElementById('contacts'); ul.innerHTML = ''; - Object.entries(contacts).forEach(([node, contact]) => { + // sort contacts alphabetically by node + Object.entries(contacts).sort((a, b) => a[0].localeCompare(b[0])).forEach(([node, contact]) => { const li = document.createElement('li'); const div = document.createElement('div'); div.classList.add('contact'); div.innerHTML = `

                    ${node}

                      - ${Object.entries(contact).map(([field, value]) => `
                    • ${field}: ${value}
                    • `).join('')} + ${Object.entries(contact).sort((a, b) => a[0].localeCompare(b[0])).map(([field, value]) => ` +
                    • + ${field}: ${JSON.stringify(value)} + +
                    • + `).join('')}
                    @@ -54,13 +60,25 @@ function populate_contacts(contacts) { e.preventDefault(); const node = this.getAttribute('id'); const data = new FormData(e.target); + let value = data.get('value'); + // if value is not valid JSON, wrap it in quotes + try { + JSON.parse(value); + } catch (e) { + // If parsing fails, assume it's a string and wrap it in quotes + value = `"${value}"`; + } api_call({ - "AddField": [node, data.get('field'), data.get('value')] + "AddField": [node, data.get('field'), value] }); }); }); } +document.getElementById('back-button').addEventListener('click', () => { + window.location.href = '/'; +}); + document.getElementById('add-contact').addEventListener('submit', (e) => { e.preventDefault(); const data = new FormData(e.target); @@ -92,6 +110,12 @@ document.getElementById('add-contact').addEventListener('submit', (e) => { }); }) +function removeField(node, field) { + api_call({ + "RemoveField": [node, field] + }); +} + // Setup WebSocket connection const wsProtocol = location.protocol === 'https:' ? 'wss://' : 'ws://'; const ws = new WebSocket(wsProtocol + location.host + "/contacts:contacts:sys/"); From 189f0378bb5ddfcf4b7ad33daae2e9ad509f7bae Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 21 Oct 2024 15:25:24 -0400 Subject: [PATCH 10/13] grant caps unnecessary in manifest --- kinode/packages/contacts/pkg/manifest.json | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/kinode/packages/contacts/pkg/manifest.json b/kinode/packages/contacts/pkg/manifest.json index dbc26269..03dd9b26 100644 --- a/kinode/packages/contacts/pkg/manifest.json +++ b/kinode/packages/contacts/pkg/manifest.json @@ -13,23 +13,7 @@ "grant_capabilities": [ "eth:distro:sys", "http_server:distro:sys", - "vfs:distro:sys", - { - "process": "main:app_store:sys", - "params": "ReadNameOnly" - }, - { - "process": "main:app_store:sys", - "params": "Read" - }, - { - "process": "main:app_store:sys", - "params": "Add" - }, - { - "process": "main:app_store:sys", - "params": "Remove" - } + "vfs:distro:sys" ], "public": false } From d4aac4e83b7184cf7cb651ddd74ec2a2218d7d90 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Mon, 21 Oct 2024 17:07:51 -0700 Subject: [PATCH 11/13] contacts: add get_names script --- kinode/packages/contacts/Cargo.lock | 46 ++++++++++++++++++- kinode/packages/contacts/Cargo.toml | 1 + kinode/packages/contacts/get_names/Cargo.toml | 19 ++++++++ kinode/packages/contacts/get_names/src/lib.rs | 35 ++++++++++++++ kinode/packages/contacts/pkg/scripts.json | 18 ++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 kinode/packages/contacts/get_names/Cargo.toml create mode 100644 kinode/packages/contacts/get_names/src/lib.rs create mode 100644 kinode/packages/contacts/pkg/scripts.json diff --git a/kinode/packages/contacts/Cargo.lock b/kinode/packages/contacts/Cargo.lock index 9df40bfb..accb072b 100644 --- a/kinode/packages/contacts/Cargo.lock +++ b/kinode/packages/contacts/Cargo.lock @@ -780,7 +780,7 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" name = "contacts" version = "0.1.0" dependencies = [ - "kinode_process_lib", + "kinode_process_lib 0.9.4", "serde", "serde_json", "wit-bindgen", @@ -1161,6 +1161,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "get-names" +version = "0.1.0" +dependencies = [ + "anyhow", + "kinode_process_lib 0.9.3", + "process_macros", + "serde", + "serde_json", + "wit-bindgen", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -1460,6 +1472,29 @@ dependencies = [ "sha3-asm", ] +[[package]] +name = "kinode_process_lib" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7722aef4bff0625445fafda89a02f82ce0e16c7def6024e1317ae55a632ad331" +dependencies = [ + "alloy", + "alloy-primitives", + "alloy-sol-macro", + "alloy-sol-types", + "anyhow", + "bincode", + "http", + "mime_guess", + "rand", + "rmp-serde", + "serde", + "serde_json", + "thiserror", + "url", + "wit-bindgen", +] + [[package]] name = "kinode_process_lib" version = "0.9.4" @@ -1887,6 +1922,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "process_macros" +version = "0.1.0" +source = "git+https://github.com/kinode-dao/process_macros?rev=626e501#626e501d351e3365480ec6f770d474ed4ae339bf" +dependencies = [ + "quote", + "syn 2.0.79", +] + [[package]] name = "proptest" version = "1.5.0" diff --git a/kinode/packages/contacts/Cargo.toml b/kinode/packages/contacts/Cargo.toml index 43e1d296..e69e3bbb 100644 --- a/kinode/packages/contacts/Cargo.toml +++ b/kinode/packages/contacts/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ "contacts", + "get_names", ] [profile.release] diff --git a/kinode/packages/contacts/get_names/Cargo.toml b/kinode/packages/contacts/get_names/Cargo.toml new file mode 100644 index 00000000..da056b75 --- /dev/null +++ b/kinode/packages/contacts/get_names/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "get-names" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +anyhow = "1.0" +kinode_process_lib = "0.9.2" +process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +wit-bindgen = "0.24.0" + +[lib] +crate-type = ["cdylib"] + +[package.metadata.component] +package = "kinode:process" diff --git a/kinode/packages/contacts/get_names/src/lib.rs b/kinode/packages/contacts/get_names/src/lib.rs new file mode 100644 index 00000000..f5ca50a7 --- /dev/null +++ b/kinode/packages/contacts/get_names/src/lib.rs @@ -0,0 +1,35 @@ +use crate::kinode::process::contacts::{Capabilities as ContactsCapability, Request as ContactsRequest, Response as ContactsResponse}; +use kinode_process_lib::{call_init, println, Address, Capability, Request}; + +wit_bindgen::generate!({ + path: "target/wit", + world: "contacts-sys-v0", + generate_unused_types: true, + additional_derives: [serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], +}); + +call_init!(init); +fn init(our: Address) { + let contacts_process = Address::from((our.node(), ("contacts", "contacts", "sys"))); + + let read_names_cap = Capability::new( + &contacts_process, + serde_json::to_string(&ContactsCapability::ReadNameOnly).unwrap() + ); + + let Ok(Ok(response)) = Request::to(&contacts_process) + .body(ContactsRequest::GetNames) + .capabilities(vec![read_names_cap]) + .send_and_await_response(5) else + { + println!("did not receive expected Response from contacts:contacts:sys"); + return; + }; + + let Ok(ContactsResponse::GetNames(names)) = response.body().try_into() else { + println!("did not receive GetNames resposne from contacts:contacts:sys"); + return; + }; + + println!("{names:?}"); +} diff --git a/kinode/packages/contacts/pkg/scripts.json b/kinode/packages/contacts/pkg/scripts.json new file mode 100644 index 00000000..80b2db1d --- /dev/null +++ b/kinode/packages/contacts/pkg/scripts.json @@ -0,0 +1,18 @@ +{ + "get_names.wasm": { + "root": false, + "public": false, + "request_networking": false, + "request_capabilities": [ + "contacts:contacts:sys", + { + "process": "contacts:contacts:sys", + "params": "ReadNameOnly" + } + ], + "grant_capabilities": [ + "contacts:contacts:sys" + ], + "wit_version": 0 + } +} From 50480bebe43512f1f55f3cabcf07b87fcb1523a1 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Tue, 22 Oct 2024 13:20:10 -0400 Subject: [PATCH 12/13] review --- Cargo.lock | 1 + kinode/packages/contacts/Cargo.lock | 1 + .../packages/contacts/api/contacts:sys-v0.wit | 4 +- kinode/packages/contacts/contacts/Cargo.toml | 1 + kinode/packages/contacts/contacts/src/lib.rs | 37 +++++++++---------- kinode/packages/contacts/get_names/src/lib.rs | 16 ++++---- kinode/packages/contacts/pkg/ui/index.html | 2 +- kinode/packages/contacts/pkg/ui/script.js | 12 ++++-- 8 files changed, 40 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cea58e23..cf8f512c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1868,6 +1868,7 @@ name = "contacts" version = "0.1.0" dependencies = [ "kinode_process_lib 0.9.4", + "process_macros", "serde", "serde_json", "wit-bindgen", diff --git a/kinode/packages/contacts/Cargo.lock b/kinode/packages/contacts/Cargo.lock index accb072b..42b714e5 100644 --- a/kinode/packages/contacts/Cargo.lock +++ b/kinode/packages/contacts/Cargo.lock @@ -781,6 +781,7 @@ name = "contacts" version = "0.1.0" dependencies = [ "kinode_process_lib 0.9.4", + "process_macros", "serde", "serde_json", "wit-bindgen", diff --git a/kinode/packages/contacts/api/contacts:sys-v0.wit b/kinode/packages/contacts/api/contacts:sys-v0.wit index 37022f1e..d9ef004e 100644 --- a/kinode/packages/contacts/api/contacts:sys-v0.wit +++ b/kinode/packages/contacts/api/contacts:sys-v0.wit @@ -1,5 +1,5 @@ interface contacts { - enum capabilities { + enum capability { read-name-only, read, add, @@ -26,7 +26,7 @@ interface contacts { add-field, remove-contact, remove-field, - error(string), // any failed request will receive this response + err(string), // any failed request will receive this response } } diff --git a/kinode/packages/contacts/contacts/Cargo.toml b/kinode/packages/contacts/contacts/Cargo.toml index b848209f..7a4e7f65 100644 --- a/kinode/packages/contacts/contacts/Cargo.toml +++ b/kinode/packages/contacts/contacts/Cargo.toml @@ -8,6 +8,7 @@ simulation-mode = [] [dependencies] kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "088a549" } +process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/contacts/contacts/src/lib.rs b/kinode/packages/contacts/contacts/src/lib.rs index f59f0a73..4fc0b82a 100644 --- a/kinode/packages/contacts/contacts/src/lib.rs +++ b/kinode/packages/contacts/contacts/src/lib.rs @@ -7,6 +7,13 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::str::FromStr; +wit_bindgen::generate!({ + path: "target/wit", + world: "contacts-sys-v0", + generate_unused_types: true, + additional_derives: [PartialEq, serde::Deserialize, serde::Serialize, process_macros::SerdeJsonInto], +}); + const ICON: &str = include_str!("icon"); #[cfg(not(feature = "simulation-mode"))] @@ -92,13 +99,6 @@ impl ContactsState { } } -wit_bindgen::generate!({ - path: "target/wit", - world: "contacts-sys-v0", - generate_unused_types: true, - additional_derives: [PartialEq, serde::Deserialize, serde::Serialize], -}); - call_init!(initialize); fn initialize(our: Address) { kiprintln!("started"); @@ -181,7 +181,7 @@ fn handle_request( } else { // if request is not from frontend, check that it has the required capabilities let (response, blob) = handle_contacts_request(state, kimap, body, Some(capabilities)); - let mut response = Response::new().body(serde_json::to_vec(&response).unwrap()); + let mut response = Response::new().body(response); if let Some(blob) = blob { response = response.blob(blob); } @@ -208,7 +208,7 @@ fn handle_http_request( "POST" => { let blob = get_blob().unwrap(); let (response, blob) = handle_contacts_request(state, kimap, blob.bytes(), None); - if let contacts::Response::Error(e) = response { + if let contacts::Response::Err(e) = response { return ( http::server::HttpResponse::new(http::StatusCode::BAD_REQUEST) .header("Content-Type", "application/json"), @@ -246,7 +246,7 @@ fn handle_contacts_request( ) -> (contacts::Response, Option) { let Ok(request) = serde_json::from_slice::(request_bytes) else { return ( - contacts::Response::Error("Malformed request".to_string()), + contacts::Response::Err("Malformed request".to_string()), None, ); }; @@ -256,22 +256,22 @@ fn handle_contacts_request( let required_capability = Capability::new( &state.our, serde_json::to_string(&match request { - contacts::Request::GetNames => contacts::Capabilities::ReadNameOnly, + contacts::Request::GetNames => contacts::Capability::ReadNameOnly, contacts::Request::GetAllContacts | contacts::Request::GetContact(_) => { - contacts::Capabilities::Read + contacts::Capability::Read } contacts::Request::AddContact(_) | contacts::Request::AddField(_) => { - contacts::Capabilities::Add + contacts::Capability::Add } contacts::Request::RemoveContact(_) | contacts::Request::RemoveField(_) => { - contacts::Capabilities::Remove + contacts::Capability::Remove } }) .unwrap(), ); if !capabilities.contains(&required_capability) { return ( - contacts::Response::Error("Missing capability".to_string()), + contacts::Response::Err("Missing capability".to_string()), None, ); } @@ -315,10 +315,7 @@ fn handle_contacts_request( return (response, blob); } let Ok(value) = serde_json::from_str::(&value) else { - return ( - contacts::Response::Error("Malformed value".to_string()), - None, - ); + return (contacts::Response::Err("Malformed value".to_string()), None); }; state.add_field(node, field, value); (contacts::Response::AddField, None) @@ -346,7 +343,7 @@ fn invalid_node( None } else { Some(( - contacts::Response::Error("Node name invalid or does not exist".to_string()), + contacts::Response::Err("Node name invalid or does not exist".to_string()), None, )) } diff --git a/kinode/packages/contacts/get_names/src/lib.rs b/kinode/packages/contacts/get_names/src/lib.rs index f5ca50a7..21ef9707 100644 --- a/kinode/packages/contacts/get_names/src/lib.rs +++ b/kinode/packages/contacts/get_names/src/lib.rs @@ -1,4 +1,4 @@ -use crate::kinode::process::contacts::{Capabilities as ContactsCapability, Request as ContactsRequest, Response as ContactsResponse}; +use crate::kinode::process::contacts; use kinode_process_lib::{call_init, println, Address, Capability, Request}; wit_bindgen::generate!({ @@ -14,20 +14,20 @@ fn init(our: Address) { let read_names_cap = Capability::new( &contacts_process, - serde_json::to_string(&ContactsCapability::ReadNameOnly).unwrap() + serde_json::to_string(&contacts::Capability::ReadNameOnly).unwrap(), ); let Ok(Ok(response)) = Request::to(&contacts_process) - .body(ContactsRequest::GetNames) + .body(contacts::Request::GetNames) .capabilities(vec![read_names_cap]) - .send_and_await_response(5) else - { - println!("did not receive expected Response from contacts:contacts:sys"); + .send_and_await_response(5) + else { + println!("did not receive expected response from contacts:contacts:sys"); return; }; - let Ok(ContactsResponse::GetNames(names)) = response.body().try_into() else { - println!("did not receive GetNames resposne from contacts:contacts:sys"); + let Ok(contacts::Response::GetNames(names)) = response.body().try_into() else { + println!("did not receive GetNames response from contacts:contacts:sys"); return; }; diff --git a/kinode/packages/contacts/pkg/ui/index.html b/kinode/packages/contacts/pkg/ui/index.html index 934795a6..fbdd0f33 100644 --- a/kinode/packages/contacts/pkg/ui/index.html +++ b/kinode/packages/contacts/pkg/ui/index.html @@ -130,7 +130,7 @@
                    - +
                    diff --git a/kinode/packages/contacts/pkg/ui/script.js b/kinode/packages/contacts/pkg/ui/script.js index ea1bd94c..153ff50a 100644 --- a/kinode/packages/contacts/pkg/ui/script.js +++ b/kinode/packages/contacts/pkg/ui/script.js @@ -36,8 +36,8 @@ function populate_contacts(contacts) {
                    - - + +
                    `; @@ -76,7 +76,13 @@ function populate_contacts(contacts) { } document.getElementById('back-button').addEventListener('click', () => { - window.location.href = '/'; + // set page to `/` while also removing the subdomain + const url = new URL(window.location.href); + if (url.hostname.split('.')[0] === 'contacts-sys') { + url.hostname = url.hostname.split('.').slice(1).join('.'); + } + url.pathname = '/'; + window.location.href = url.toString(); }); document.getElementById('add-contact').addEventListener('submit', (e) => { From 670eec3e6cc99ee2432baf7acaa0687f1ac7f3d2 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Tue, 22 Oct 2024 13:43:01 -0400 Subject: [PATCH 13/13] spacing --- kinode/packages/contacts/api/contacts:sys-v0.wit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kinode/packages/contacts/api/contacts:sys-v0.wit b/kinode/packages/contacts/api/contacts:sys-v0.wit index d9ef004e..546dfd24 100644 --- a/kinode/packages/contacts/api/contacts:sys-v0.wit +++ b/kinode/packages/contacts/api/contacts:sys-v0.wit @@ -26,7 +26,7 @@ interface contacts { add-field, remove-contact, remove-field, - err(string), // any failed request will receive this response + err(string), // any failed request will receive this response } }