diff --git a/Cargo.lock b/Cargo.lock index 00cdd18..f7cb075 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -50,8 +56,8 @@ dependencies = [ "axum", "bytes", "cfg-if", - "http", - "indexmap", + "http 1.1.0", + "indexmap 2.4.0", "schemars", "serde", "serde_json", @@ -81,29 +87,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] -name = "alloy-consensus" -version = "0.2.1" +name = "alloy" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" +dependencies = [ + "alloy-consensus", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-provider", + "alloy-rpc-client", + "alloy-serde", + "alloy-signer", + "alloy-signer-aws", + "alloy-signer-gcp", + "alloy-signer-ledger", + "alloy-transport-http", +] + +[[package]] +name = "alloy-chains" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c309895995eaa4bfcc345f5515a39c7df9447798645cc8bf462b6c5bf1dc96" +checksum = "bb07629a5d0645d29f68d2fb6f4d0cf15c89ec0965be915f303967180929743f" +dependencies = [ + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ "alloy-eips", - "alloy-primitives 0.7.7", + "alloy-primitives", "alloy-rlp", "alloy-serde", "c-kzg", "serde", ] +[[package]] +name = "alloy-core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6dbb79f4e3285cc87f50c0d4be9a3a812643623b2e3558d425b41cbd795ceb" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] + [[package]] name = "alloy-dyn-abi" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" +checksum = "ba5b68572f5dfa99ede0a491d658c9842626c956b840d0b97d0bbc9637742504" dependencies = [ - "alloy-json-abi 0.7.7", - "alloy-primitives 0.7.7", - "alloy-sol-type-parser 0.7.7", - "alloy-sol-types 0.7.7", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", "const-hex", "derive_more", "itoa", @@ -113,12 +159,35 @@ dependencies = [ ] [[package]] -name = "alloy-eips" -version = "0.2.1" +name = "alloy-eip2930" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9431c99a3b3fe606ede4b3d4043bdfbcb780c45b8d8d226c3804e2b75cfbe68" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ - "alloy-primitives 0.7.7", + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d319bb544ca6caeab58c39cea8921c55d924d4f68f2c60f24f914673f9a74a" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eips" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", "alloy-rlp", "alloy-serde", "c-kzg", @@ -128,15 +197,13 @@ dependencies = [ ] [[package]] -name = "alloy-json-abi" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc05b04ac331a9f07e3a4036ef7926e49a8bf84a99a1ccfc7e2ab55a5fcbb372" +name = "alloy-genesis" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-primitives 0.7.7", - "alloy-sol-type-parser 0.7.7", + "alloy-primitives", + "alloy-serde", "serde", - "serde_json", ] [[package]] @@ -145,20 +212,19 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "299d2a937b6c60968df3dad2a988b0f0e03277b344639a4f7a31bd68e6285e59" dependencies = [ - "alloy-primitives 0.8.0", - "alloy-sol-type-parser 0.8.0", + "alloy-primitives", + "alloy-sol-type-parser", "serde", "serde_json", ] [[package]] name = "alloy-json-rpc" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e2865c4c3bb4cdad3f0d9ec1ab5c0c657ba69a375651bd35e32fb6c180ccc2" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-primitives 0.7.7", - "alloy-sol-types 0.7.7", + "alloy-primitives", + "alloy-sol-types", "serde", "serde_json", "thiserror", @@ -167,19 +233,18 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e701fc87ef9a3139154b0b4ccb935b565d27ffd9de020fe541bf2dec5ae4ede" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network-primitives", - "alloy-primitives 0.7.7", + "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", "alloy-signer", - "alloy-sol-types 0.7.7", + "alloy-sol-types", "async-trait", "auto_impl", "futures-utils-wasm", @@ -188,20 +253,19 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec9d5a0f9170b10988b6774498a022845e13eda94318440d17709d50687f67f9" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-primitives 0.7.7", + "alloy-primitives", "alloy-serde", "serde", ] [[package]] name = "alloy-primitives" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +checksum = "a767e59c86900dd7c3ce3ecef04f3ace5ac9631ee150beb8b7d22f7fa3bbb2d7" dependencies = [ "alloy-rlp", "bytes", @@ -220,25 +284,36 @@ dependencies = [ ] [[package]] -name = "alloy-primitives" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a767e59c86900dd7c3ce3ecef04f3ace5ac9631ee150beb8b7d22f7fa3bbb2d7" +name = "alloy-provider" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "hex-literal", - "itoa", - "k256", - "keccak-asm", - "proptest", - "rand", - "ruint", + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "futures-utils-wasm", + "lru", + "pin-project 1.1.5", + "reqwest", "serde", - "tiny-keccak", + "serde_json", + "thiserror", + "tokio", + "tracing", + "url", ] [[package]] @@ -263,19 +338,38 @@ dependencies = [ "syn 2.0.76", ] +[[package]] +name = "alloy-rpc-client" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project 1.1.5", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + [[package]] name = "alloy-rpc-types-eth" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e18424d962d7700a882fe423714bd5b9dde74c7a7589d4255ea64068773aef" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-network-primitives", - "alloy-primitives 0.7.7", + "alloy-primitives", "alloy-rlp", "alloy-serde", - "alloy-sol-types 0.7.7", + "alloy-sol-types", "itertools 0.13.0", "serde", "serde_json", @@ -284,24 +378,22 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33feda6a53e6079895aed1d08dcb98a1377b000d80d16370fbbdb8155d547ef" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-primitives 0.7.7", + "alloy-primitives", "serde", "serde_json", ] [[package]] name = "alloy-signer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740a25b92e849ed7b0fa013951fe2f64be9af1ad5abe805037b44fb7770c5c47" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ "alloy-dyn-abi", - "alloy-primitives 0.7.7", - "alloy-sol-types 0.7.7", + "alloy-primitives", + "alloy-sol-types", "async-trait", "auto_impl", "elliptic-curve", @@ -310,65 +402,70 @@ dependencies = [ ] [[package]] -name = "alloy-signer-local" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0707d4f63e4356a110b30ef3add8732ab6d181dd7be4607bf79b8777105cee" +name = "alloy-signer-aws" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 0.7.7", + "alloy-primitives", "alloy-signer", "async-trait", + "aws-sdk-kms", "k256", - "rand", + "spki", "thiserror", + "tracing", ] [[package]] -name = "alloy-sol-macro" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b40397ddcdcc266f59f959770f601ce1280e699a91fc1862f29cef91707cd09" +name = "alloy-signer-gcp" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-sol-macro-expander 0.7.7", - "alloy-sol-macro-input 0.7.7", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.76", + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "gcloud-sdk", + "k256", + "spki", + "thiserror", + "tracing", ] [[package]] -name = "alloy-sol-macro" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183bcfc0f3291d9c41a3774172ee582fb2ce6eb6569085471d8f225de7bb86fc" +name = "alloy-signer-ledger" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-sol-macro-expander 0.8.0", - "alloy-sol-macro-input 0.8.0", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.76", + "alloy-consensus", + "alloy-dyn-abi", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "coins-ledger", + "futures-util", + "semver 1.0.23", + "thiserror", + "tracing", ] [[package]] -name = "alloy-sol-macro-expander" -version = "0.7.7" +name = "alloy-sol-macro" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "867a5469d61480fea08c7333ffeca52d5b621f5ca2e44f271b117ec1fc9a0525" +checksum = "183bcfc0f3291d9c41a3774172ee582fb2ce6eb6569085471d8f225de7bb86fc" dependencies = [ - "alloy-sol-macro-input 0.7.7", - "const-hex", - "heck 0.5.0", - "indexmap", + "alloy-sol-macro-expander", + "alloy-sol-macro-input", "proc-macro-error", "proc-macro2", "quote", "syn 2.0.76", - "syn-solidity 0.7.7", - "tiny-keccak", ] [[package]] @@ -377,33 +474,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71c4d842beb7a6686d04125603bc57614d5ed78bf95e4753274db3db4ba95214" dependencies = [ - "alloy-sol-macro-input 0.8.0", + "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap", + "indexmap 2.4.0", "proc-macro-error", "proc-macro2", "quote", "syn 2.0.76", - "syn-solidity 0.8.0", + "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.76", - "syn-solidity 0.7.7", -] - [[package]] name = "alloy-sol-macro-input" version = "0.8.0" @@ -416,52 +498,62 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.76", - "syn-solidity 0.8.0", + "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" +checksum = "f4691da83dce9c9b4c775dd701c87759f173bd3021cbf2e60cde00c5fe6d7241" dependencies = [ "serde", "winnow", ] [[package]] -name = "alloy-sol-type-parser" +name = "alloy-sol-types" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4691da83dce9c9b4c775dd701c87759f173bd3021cbf2e60cde00c5fe6d7241" +checksum = "577e262966e92112edbd15b1b2c0947cc434d6e8311df96d3329793fe8047da9" dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", "serde", - "winnow", ] [[package]] -name = "alloy-sol-types" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91ca40fa20793ae9c3841b83e74569d1cc9af29a2f5237314fd3452d51e38c7" +name = "alloy-transport" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-primitives 0.7.7", - "alloy-sol-macro 0.7.7", - "const-hex", + "alloy-json-rpc", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", ] [[package]] -name = "alloy-sol-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577e262966e92112edbd15b1b2c0947cc434d6e8311df96d3329793fe8047da9" +name = "alloy-transport-http" +version = "0.3.0" +source = "git+https://github.com/alloy-rs/alloy.git#352e83bfcf537ed9519decc10b9853b2d56ace95" dependencies = [ - "alloy-json-abi 0.8.0", - "alloy-primitives 0.8.0", - "alloy-sol-macro 0.8.0", - "const-hex", - "serde", + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", ] [[package]] @@ -615,6 +707,41 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-compression" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + [[package]] name = "async-trait" version = "0.1.81" @@ -642,21 +769,342 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "auto_impl" -version = "1.2.0" +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.76", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "aws-config" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e95816a168520d72c0e7680c405a5a8c1fb6a035b4bc4b9d7b0de8e1a941697" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 0.2.12", + "ring", + "time", + "tokio", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16838e6c9e12125face1c1eff1343c75e3ff540de98ff7ebd61874a89bcfeb9" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-runtime" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42c2d4218de4dcd890a109461e2f799a1a2ba3bcd2cde9af88360f5df9266c6" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-kms" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ebbbc319551583b9233a74b359ede7349102e779fc12371d2478e80b50d218" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sso" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11822090cf501c316c6f75711d77b96fba30658e3867a7762e5e2f5d32d31e81" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a2a06ff89176123945d1bbe865603c4d7101bea216a550bb4d2e4e9ba74d74" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20a91795850826a6f456f4a48eff1dfa59a0e69bdbf5b8c50518fd372106574" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5df1b0fa6be58efe9d4ccc257df0a53b89cd8909e86591a13ca54817c87517be" +dependencies = [ + "aws-credential-types", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "form_urlencoded", + "hex", + "hmac", + "http 0.2.12", + "http 1.1.0", + "once_cell", + "percent-encoding", + "sha2", + "time", + "tracing", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-http" +version = "0.60.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9cd0ae3d97daa0a2bf377a4d8e8e1362cae590c4a1aad0d40058ebca18eb91e" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.60.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abbf454960d0db2ad12684a1640120e7557294b0ff8e2f11236290a1b293225" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.1", + "httparse", + "hyper 0.14.30", + "hyper-rustls 0.24.2", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls 0.21.12", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e086682a53d3aa241192aa110fa8dfce98f2f5ac2ead0de84d41582c7e8fdb96" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.1.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-types" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cee7cadb433c781d3299b916fbf620fea813bf38f49db282fb6858141a05cc8" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.1.0", + "http-body 0.4.6", + "http-body 1.0.1", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +checksum = "d123fbc2a4adc3c301652ba8e149bf4bc1d1725affb9784eb20c953ace06bf55" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.76", + "xmlparser", ] [[package]] -name = "autocfg" -version = "1.3.0" +name = "aws-types" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "5221b91b3e441e6675310829fd8984801b772cb1546ef6c0e54dec9f1ac13fef" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "rustc_version 0.4.0", + "tracing", +] [[package]] name = "axum" @@ -668,10 +1116,10 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -701,8 +1149,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -722,8 +1170,8 @@ dependencies = [ "aide", "async-trait", "axum", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", "itertools 0.12.1", "jsonschema", "schemars", @@ -743,7 +1191,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -766,6 +1214,16 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + [[package]] name = "base64ct" version = "1.6.0" @@ -868,6 +1326,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + [[package]] name = "c-kzg" version = "1.0.3" @@ -913,6 +1381,29 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "coins-ledger" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9bc0994d0aa0f4ade5f3a9baf4a8d936f250278c85a1124b401860454246ab" +dependencies = [ + "async-trait", + "byteorder", + "cfg-if", + "const-hex", + "getrandom", + "hidapi-rusb", + "js-sys", + "log", + "nix", + "once_cell", + "thiserror", + "tokio", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -987,6 +1478,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -1065,6 +1565,20 @@ dependencies = [ "syn 2.0.76", ] +[[package]] +name = "dashmap" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "der" version = "0.7.9" @@ -1183,6 +1697,7 @@ dependencies = [ "ff", "generic-array", "group", + "pem-rfc7468", "pkcs8", "rand_core", "sec1", @@ -1292,6 +1807,16 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "flume" version = "0.11.0" @@ -1455,6 +1980,34 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" +[[package]] +name = "gcloud-sdk" +version = "0.25.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77045256cd0d2075e09d62c4c9f27c2b664e2cc806d7ddf3a4293bb0c20b4728" +dependencies = [ + "async-trait", + "bytes", + "chrono", + "futures", + "hyper 1.4.1", + "jsonwebtoken", + "once_cell", + "prost", + "prost-types", + "reqwest", + "secret-vault-value", + "serde", + "serde_json", + "tokio", + "tonic", + "tower", + "tower-layer", + "tower-util", + "tracing", + "url", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1502,6 +2055,25 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.4.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.6" @@ -1513,14 +2085,20 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", - "indexmap", + "http 1.1.0", + "indexmap 2.4.0", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1537,7 +2115,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1546,7 +2124,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1585,6 +2163,18 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hidapi-rusb" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efdc2ec354929a6e8f3c6b6923a4d97427ec2f764cfee8cd4bfe890946cdf08b" +dependencies = [ + "cc", + "libc", + "pkg-config", + "rusb", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -1612,6 +2202,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.1.0" @@ -1623,6 +2224,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -1630,7 +2242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.1.0", ] [[package]] @@ -1641,8 +2253,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -1658,6 +2270,30 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hyper" +version = "0.14.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.4.1" @@ -1667,9 +2303,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -1679,6 +2315,22 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.30", + "log", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.27.2" @@ -1686,13 +2338,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", - "http", - "hyper", + "http 1.1.0", + "hyper 1.4.1", "hyper-util", - "rustls", + "rustls 0.23.12", + "rustls-native-certs 0.7.2", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper 1.4.1", + "hyper-util", + "pin-project-lite", + "tokio", "tower-service", ] @@ -1704,7 +2370,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper", + "hyper 1.4.1", "hyper-util", "native-tls", "tokio", @@ -1721,9 +2387,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -1767,7 +2433,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1428f8183b5df215f8b620cc2529fa284e93a97391b74461c6b6b5ebc9d4f2f4" dependencies = [ - "alloy-sol-types 0.8.0", + "alloy-sol-types", "base64 0.21.7", "reqwest", "ring", @@ -1811,6 +2477,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.4.0" @@ -1818,7 +2494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", "serde", ] @@ -1907,6 +2583,21 @@ dependencies = [ "uuid", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" +dependencies = [ + "base64 0.21.7", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "k256" version = "0.13.3" @@ -1962,6 +2653,18 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libusb1-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da050ade7ac4ff1ba5379af847a10a10a8e284181e060105bf8d86960ce9ce0f" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1984,6 +2687,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2015,12 +2727,31 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[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 = "minimal-lexical" version = "0.2.1" @@ -2036,6 +2767,15 @@ dependencies = [ "adler", ] +[[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" @@ -2065,6 +2805,19 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + [[package]] name = "nom" version = "7.1.3" @@ -2198,6 +2951,26 @@ dependencies = [ "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.76", +] + [[package]] name = "object" version = "0.36.3" @@ -2257,6 +3030,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + [[package]] name = "overload" version = "0.1.1" @@ -2322,7 +3101,17 @@ dependencies = [ name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] [[package]] name = "pem-rfc7468" @@ -2350,13 +3139,33 @@ dependencies = [ "ucd-trie", ] +[[package]] +name = "pin-project" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef0f924a5ee7ea9cbcea77529dba45f8a9ba9f622419fe3386ca581a3ae9d5a" +dependencies = [ + "pin-project-internal 0.4.30", +] + [[package]] name = "pin-project" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ - "pin-project-internal", + "pin-project-internal 1.1.5", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -2497,12 +3306,92 @@ dependencies = [ "unarray", ] +[[package]] +name = "prost" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "prost-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" +dependencies = [ + "prost", +] + [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.12", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls 0.23.12", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.37" @@ -2607,6 +3496,12 @@ dependencies = [ "regex-syntax 0.8.4", ] +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -2625,28 +3520,34 @@ version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ + "async-compression", "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", "http-body-util", - "hyper", - "hyper-rustls", + "hyper 1.4.1", + "hyper-rustls 0.27.2", "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "mime_guess", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "quinn", + "rustls 0.23.12", + "rustls-native-certs 0.7.2", + "rustls-pemfile 2.1.3", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", @@ -2654,10 +3555,13 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.0", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "windows-registry", ] @@ -2747,12 +3651,28 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" +[[package]] +name = "rusb" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9f9ff05b63a786553a4c02943b74b34a988448671001e9a27e2f0565cc05a4" +dependencies = [ + "libc", + "libusb1-sys", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -2790,20 +3710,67 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + [[package]] name = "rustls" version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ + "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.7", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.3", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustls-pemfile" version = "2.1.3" @@ -2820,6 +3787,16 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustls-webpki" version = "0.102.7" @@ -2872,7 +3849,7 @@ checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "chrono", "dyn-clone", - "indexmap", + "indexmap 2.4.0", "schemars_derive", "serde", "serde_json", @@ -2896,6 +3873,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sec1" version = "0.7.3" @@ -2910,6 +3897,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secret-vault-value" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc32a777b53b3433b974c9c26b6d502a50037f8da94e46cb8ce2ced2cfdfaea0" +dependencies = [ + "prost", + "prost-types", + "serde", + "serde_json", + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -3101,6 +4101,18 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + [[package]] name = "slab" version = "0.4.9" @@ -3203,7 +4215,7 @@ dependencies = [ "futures-util", "hashlink 0.8.4", "hex", - "indexmap", + "indexmap 2.4.0", "log", "memchr", "once_cell", @@ -3240,17 +4252,17 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown", + "hashbrown 0.14.5", "hashlink 0.9.1", "hex", - "indexmap", + "indexmap 2.4.0", "log", "memchr", "once_cell", "paste", "percent-encoding", - "rustls", - "rustls-pemfile", + "rustls 0.23.12", + "rustls-pemfile 2.1.3", "serde", "serde_json", "sha2", @@ -3519,6 +4531,28 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[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.76", +] + [[package]] name = "subtle" version = "2.6.1" @@ -3547,18 +4581,6 @@ dependencies = [ "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.76", -] - [[package]] name = "syn-solidity" version = "0.8.0" @@ -3672,6 +4694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde", @@ -3758,13 +4781,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls", + "rustls 0.23.12", "rustls-pki-types", "tokio", ] @@ -3778,6 +4811,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util", ] [[package]] @@ -3805,11 +4839,44 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap", + "indexmap 2.4.0", "toml_datetime", "winnow", ] +[[package]] +name = "tonic" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project 1.1.5", + "prost", + "rustls-native-certs 0.7.2", + "rustls-pemfile 2.1.3", + "socket2", + "tokio", + "tokio-rustls 0.26.0", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -3818,9 +4885,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "pin-project", + "indexmap 1.9.3", + "pin-project 1.1.5", "pin-project-lite", + "rand", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -3838,6 +4909,18 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +[[package]] +name = "tower-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1093c19826d33807c72511e68f73b4a0469a3f22c2bd5f7d5212178b4b89674" +dependencies = [ + "futures-core", + "futures-util", + "pin-project 0.4.30", + "tower-service", +] + [[package]] name = "tracing" version = "0.1.40" @@ -3936,6 +5019,15 @@ 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.15" @@ -4026,6 +5118,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "wait-timeout" version = "0.2.0" @@ -4123,6 +5221,19 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +[[package]] +name = "wasm-streams" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.70" @@ -4375,17 +5486,16 @@ name = "wld-usernames" version = "0.1.0" dependencies = [ "aide", - "alloy-primitives 0.7.7", - "alloy-signer", - "alloy-signer-local", - "alloy-sol-types 0.7.7", + "alloy", "anyhow", + "aws-config", + "aws-sdk-kms", "axum", "axum-jsonschema", "chrono", "dotenvy", "hex", - "http", + "http 1.1.0", "idkit", "num-traits", "regex", @@ -4411,6 +5521,12 @@ dependencies = [ "tap", ] +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index 7d6767f..7efefc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,24 +17,27 @@ dotenvy = "0.15.7" thiserror = "1.0.63" num-traits = "0.2.19" serde_json = "1.0.127" -alloy-sol-types = "0.7.7" +aws-sdk-kms = "1.40.0" tokio = { version = "1.39.3", features = ["full"] } chrono = { version = "0.4.38", features = ["serde"] } reqwest = { version = "0.12.7", features = ["json"] } serde = { version = "1.0.209", features = ["derive"] } schemars = { version = "0.8.21", features = ["chrono"] } -alloy-signer = { version = "0.2.1", features = ["eip712"] } axum-jsonschema = { version = "0.8.0", features = ["aide"] } -alloy-primitives = { version = "0.7.7", features = ["serde"] } -alloy-signer-local = { version = "0.2.1", features = ["eip712"] } aide = { version = "0.13.4", features = ["axum", "macros", "scalar"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +aws-config = { version = "1.5.5", features = ["behavior-version-latest"] } ruint = { version = "1.12.3", default-features = false, features = [ "num-traits", ] } sqlxinsert = { version = "0.10.0", default-features = false, features = [ "postgres", ] } +alloy = { git = "https://github.com/alloy-rs/alloy.git", features = [ + "eip712", + "signer-aws", + "sol-types", +] } sqlx = { version = "0.8.1", features = [ "runtime-tokio-rustls", "any", diff --git a/build.rs b/build.rs index 7e41343..c5425f0 100644 --- a/build.rs +++ b/build.rs @@ -2,28 +2,28 @@ use chrono::prelude::{DateTime, Utc}; use std::process::Command; fn get_git_rev() -> Option { - let output = Command::new("git") - .args(["rev-parse", "--short", "HEAD"]) - .output() - .ok()?; + let output = Command::new("git") + .args(["rev-parse", "--short", "HEAD"]) + .output() + .ok()?; - if output.status.success() { - String::from_utf8(output.stdout).ok() - } else { - None - } + if output.status.success() { + String::from_utf8(output.stdout).ok() + } else { + None + } } fn get_compile_date() -> String { - let system_time = std::time::SystemTime::now(); - let date_time: DateTime = system_time.into(); - format!("{}", date_time.format("%+")) + let system_time = std::time::SystemTime::now(); + let date_time: DateTime = system_time.into(); + format!("{}", date_time.format("%+")) } fn main() { - println!("cargo:rustc-env=STATIC_BUILD_DATE={}", get_compile_date()); + println!("cargo:rustc-env=STATIC_BUILD_DATE={}", get_compile_date()); - if let Some(rev) = get_git_rev() { - println!("cargo:rustc-env=GIT_REV={}", rev); - } + if let Some(rev) = get_git_rev() { + println!("cargo:rustc-env=GIT_REV={}", rev); + } } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..5c94ef6 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,8 @@ +tab_spaces = 4 +hard_tabs = true +edition = "2021" +use_try_shorthand = true +imports_granularity = "Crate" +use_field_init_shorthand = true +condense_wildcard_suffixes = true +match_block_trailing_comma = true diff --git a/src/blocklist.rs b/src/blocklist.rs index f4049a0..af87484 100644 --- a/src/blocklist.rs +++ b/src/blocklist.rs @@ -1,54 +1,53 @@ use axum::Extension; use std::{collections::HashSet, sync::Arc}; +#[allow(clippy::module_name_repetitions)] +pub type BlocklistExt = Extension>; + /// A blocklist of usernames and substrings. pub struct Blocklist { - /// A list of reserved usernames - names: HashSet>, - /// A list of substrings that are not allowed in usernames - substrings: Vec, + /// A list of reserved usernames + names: HashSet>, + /// A list of substrings that are not allowed in usernames + substrings: Vec, } #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("The requested username is reserved.")] - Reserved, - #[error("Usernames cannot contain the word \"{0}\".")] - Contains(String), + #[error("The requested username is reserved.")] + Reserved, + #[error("Usernames cannot contain the word \"{0}\".")] + Contains(String), } impl Blocklist { - /// Create a new blocklist from the given strings. - /// - `blocked_names` is a comma-separated list of blocked usernames - /// - `blocked_substrings` is a comma-separated list of blocked substrings - pub fn new(blocked_names: &str, blocked_substrings: &str) -> Self { - let names = blocked_names.split(',').map(|s| s.trim().into()).collect(); - let substrings = blocked_substrings - .split(',') - .map(|s| s.trim().into()) - .collect(); - - Self { names, substrings } - } - - /// Check if a username is blocked. - pub fn ensure_valid(&self, username: &str) -> Result<(), Error> { - if self.names.contains(username) { - return Err(Error::Reserved); - }; - - if let Some(substring) = self - .substrings - .iter() - .find(|s| username.contains(s.as_str())) - { - return Err(Error::Contains(substring.clone())); - }; - - Ok(()) - } - - pub fn extension(self) -> Extension> { - Extension(Arc::new(self)) - } + /// Create a new blocklist from the given strings. + /// - `blocked_names` is a comma-separated list of blocked usernames + /// - `blocked_substrings` is a comma-separated list of blocked substrings + pub fn new(blocked_names: &str, blocked_substrings: &str) -> Self { + let names = blocked_names.split(',').map(|s| s.trim().into()).collect(); + let substrings = blocked_substrings + .split(',') + .map(|s| s.trim().into()) + .collect(); + + Self { names, substrings } + } + + /// Check if a username is blocked. + pub fn ensure_valid(&self, username: &str) -> Result<(), Error> { + if self.names.contains(username) { + return Err(Error::Reserved); + }; + + if let Some(substring) = self + .substrings + .iter() + .find(|s| username.contains(s.as_str())) + { + return Err(Error::Contains(substring.clone())); + }; + + Ok(()) + } } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..8f83c12 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,79 @@ +use alloy::primitives::{keccak256, FixedBytes}; +use axum::Extension; +use idkit::session::AppId; +use sqlx::{postgres::PgPoolOptions, PgPool}; +use std::{ + env::{self, VarError}, + num::ParseIntError, + sync::Arc, + time::Duration, +}; + +use crate::blocklist::{Blocklist, BlocklistExt}; + +#[allow(clippy::module_name_repetitions)] +pub type ConfigExt = Extension>; + +pub struct Config { + pub wld_app_id: AppId, + pub ens_chain_id: u64, + pub ens_domain: String, + pub kms_key_id: String, + db_client: Option, + blocklist: Option, + kms_client: Option, + pub ens_resolver_salt: FixedBytes<32>, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error(transparent)] + Env(#[from] VarError), + #[error(transparent)] + Sqlx(#[from] sqlx::Error), + #[error(transparent)] + ChainId(#[from] ParseIntError), +} + +impl Config { + pub async fn from_env() -> Result { + let blocklist = Blocklist::new( + &env::var("RESERVED_USERNAMES")?, + &env::var("BLOCKED_SUBSTRINGS")?, + ); + + let db_client = PgPoolOptions::new() + .acquire_timeout(Duration::from_secs(3)) + .connect(&env::var("DATABASE_URL")?) + .await?; + + let kms_client = aws_sdk_kms::Client::new(&aws_config::load_from_env().await); + + Ok(Self { + db_client: Some(db_client), + blocklist: Some(blocklist), + kms_client: Some(kms_client), + kms_key_id: env::var("KMS_KEY_ID")?, + ens_domain: env::var("ENS_DOMAIN")?, + ens_chain_id: env::var("ENS_CHAIN_ID")?.parse()?, + ens_resolver_salt: keccak256(env::var("ENS_RESOLVER_SALT")?), + wld_app_id: unsafe { AppId::new_unchecked(env::var("WLD_APP_ID")?) }, + }) + } + + pub fn db_extension(&mut self) -> Extension { + Extension(self.db_client.take().unwrap()) + } + + pub fn blocklist_extension(&mut self) -> BlocklistExt { + Extension(Arc::new(self.blocklist.take().unwrap())) + } + + pub fn kms_extension(&mut self) -> Extension { + Extension(self.kms_client.take().unwrap()) + } + + pub fn extension(self) -> ConfigExt { + Extension(Arc::new(self)) + } +} diff --git a/src/main.rs b/src/main.rs index 6c41ca7..1e790a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,56 +1,28 @@ #![warn(clippy::all, clippy::pedantic, clippy::nursery)] -use anyhow::{bail, Result}; -use blocklist::Blocklist; +use anyhow::Result; +use config::Config; use dotenvy::dotenv; -use sqlx::postgres::PgPoolOptions; -use std::{env, time::Duration}; use tracing_subscriber::{ - prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, + prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, }; mod blocklist; +mod config; mod routes; mod server; mod types; mod utils; -static ENV_VARS: &[&str] = &[ - "ENS_DOMAIN", - "DATABASE_URL", - "WORLD_ID_APP_ID", - "ENS_RESOLVER_SALT", - "RESERVED_USERNAMES", - "BLOCKED_SUBSTRINGS", - "ENS_SIGNER_PRIVATE_KEY", -]; - #[tokio::main] async fn main() -> Result<()> { - dotenv().ok(); - - tracing_subscriber::registry() - .with(tracing_subscriber::fmt::layer().with_filter( - EnvFilter::try_from_default_env().unwrap_or_else(|_| "wld_usernames=info".into()), - )) - .init(); - - for var in ENV_VARS { - if env::var(var).is_err() { - bail!("Missing environment variable: ${var}"); - } - } - - let blocklist = Blocklist::new( - &env::var("RESERVED_USERNAMES").unwrap(), - &env::var("BLOCKED_SUBSTRINGS").unwrap(), - ); + dotenv().ok(); - let postgres = PgPoolOptions::new() - .acquire_timeout(Duration::from_secs(3)) - .connect(&env::var("DATABASE_URL").unwrap()) - .await - .expect("failed to connect to database"); + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer().with_filter( + EnvFilter::try_from_default_env().unwrap_or_else(|_| "wld_usernames=info".into()), + )) + .init(); - server::start(postgres, blocklist).await + server::start(Config::from_env().await?).await } diff --git a/src/routes/api/mod.rs b/src/routes/api/mod.rs index 31eadaf..cbbdb6c 100644 --- a/src/routes/api/mod.rs +++ b/src/routes/api/mod.rs @@ -3,5 +3,5 @@ use aide::axum::ApiRouter; mod v1; pub fn handler() -> ApiRouter { - ApiRouter::new().nest("/v1", v1::handler()) + ApiRouter::new().nest("/v1", v1::handler()) } diff --git a/src/routes/api/v1/ens_gateway.rs b/src/routes/api/v1/ens_gateway.rs index 076e71b..11895ec 100644 --- a/src/routes/api/v1/ens_gateway.rs +++ b/src/routes/api/v1/ens_gateway.rs @@ -1,127 +1,137 @@ -use alloy_primitives::keccak256; -use alloy_primitives::Address; -use alloy_signer::Signer; -use alloy_signer_local::PrivateKeySigner; -use alloy_sol_types::{eip712_domain, SolCall, SolValue}; +use alloy::{ + primitives::{keccak256, Address}, + signers::{aws::AwsSigner, Signer}, + sol_types::{eip712_domain, SolCall, SolValue}, +}; use axum::Extension; use axum_jsonschema::Json; use chrono::{TimeDelta, Utc}; use num_traits::FromPrimitive; use ruint::Uint; use sqlx::PgPool; -use std::env; -use std::str::FromStr; +use std::sync::Arc; -use crate::types::Method; use crate::{ - types::{ - ENSErrorResponse, ENSQueryPayload, ENSResponse, GatewayResponse, Name, ResolveRequest, - }, - utils::namehash, + config::{Config, ConfigExt}, + types::{ + ENSErrorResponse, ENSQueryPayload, ENSResponse, GatewayResponse, Method, Name, + ResolveRequest, + }, + utils::namehash, }; pub async fn ens_gateway( - Extension(db): Extension, - Json(request_payload): Json, + Extension(config): ConfigExt, + Extension(db): Extension, + Extension(kms_client): Extension, + Json(request_payload): Json, ) -> Result, ENSErrorResponse> { - let (req_data, name, method) = decode_payload(&request_payload) - .map_err(|_| ENSErrorResponse::new("Failed to decode payload."))?; - - let username = name - .strip_suffix(&format!(".{}", env::var("ENS_DOMAIN").unwrap())) - .ok_or_else(|| ENSErrorResponse::new("Name not found."))?; - - let record = sqlx::query_as!(Name, "SELECT * FROM names WHERE username = $1", username) - .fetch_one(&db) - .await - .map_err(|_| ENSErrorResponse::new("Name not found."))?; - - let result = match method { - Method::Text(node, key) => { - if node != namehash(&name) { - return Err(ENSErrorResponse::new("Invalid node hash provided.")); - } - - // Support for other will be implemented in the future. - if key != "avatar" { - return Err(ENSErrorResponse::new(&format!("Record not found: {key}",))); - } - - todo!("Add avatar support"); - } - Method::Addr(node) => { - if node != namehash(&name) { - return Err(ENSErrorResponse::new("Invalid node hash provided.")); - } - - (Address::parse_checksummed(record.address, None).unwrap()).abi_encode() - } - Method::AddrMultichain | Method::Name => { - return Err(ENSErrorResponse::new("Not implemented.")); - } - _ => ().abi_encode(), - }; - - sign_response(result, &req_data, request_payload.sender) - .await - .map(|data| Json(ENSResponse { data })) - .map_err(|_| ENSErrorResponse::new("Failed to sign response.")) + let (req_data, name, method) = decode_payload(&request_payload) + .map_err(|_| ENSErrorResponse::new("Failed to decode payload."))?; + + let username = name + .strip_suffix(&format!(".{}", config.ens_domain)) + .ok_or_else(|| ENSErrorResponse::new("Name not found."))?; + + let record = sqlx::query_as!(Name, "SELECT * FROM names WHERE username = $1", username) + .fetch_one(&db) + .await + .map_err(|_| ENSErrorResponse::new("Name not found."))?; + + let result = match method { + Method::Text(node, key) => { + if node != namehash(&name) { + return Err(ENSErrorResponse::new("Invalid node hash provided.")); + } + + // Support for other will be implemented in the future. + if key != "avatar" { + return Err(ENSErrorResponse::new(&format!("Record not found: {key}",))); + } + + todo!("Add avatar support"); + }, + Method::Addr(node) => { + if node != namehash(&name) { + return Err(ENSErrorResponse::new("Invalid node hash provided.")); + } + + (Address::parse_checksummed(record.address, None).unwrap()).abi_encode() + }, + Method::AddrMultichain | Method::Name => { + return Err(ENSErrorResponse::new("Not implemented.")); + }, + _ => ().abi_encode(), + }; + + sign_response( + kms_client, + config, + result, + &req_data, + request_payload.sender, + ) + .await + .map(|data| Json(ENSResponse { data })) + .map_err(|_| ENSErrorResponse::new("Failed to sign response.")) } pub fn docs(op: aide::transform::TransformOperation) -> aide::transform::TransformOperation { - op.description("CCIP Read Gateway powering the ENS integration.") + op.description("CCIP Read Gateway powering the ENS integration.") } fn decode_payload(payload: &ENSQueryPayload) -> Result<(Vec, String, Method), anyhow::Error> { - let req_data = hex::decode(&payload.data[2..])?; - let decoded_req = ResolveRequest::abi_decode(&req_data, true)?; - - Ok(( - req_data, - decoded_req.parse_name()?, - decoded_req.parse_method()?, - )) + let req_data = hex::decode(&payload.data[2..])?; + let decoded_req = ResolveRequest::abi_decode(&req_data, true)?; + + Ok(( + req_data, + decoded_req.parse_name()?, + decoded_req.parse_method()?, + )) } async fn sign_response( - response: Vec, - request_data: &[u8], - sender: crate::types::Address, + kms_client: aws_sdk_kms::Client, + config: Arc, + response: Vec, + request_data: &[u8], + sender: crate::types::Address, ) -> Result { - let expires_at = Uint::from_i64( - Utc::now() - .checked_add_signed(TimeDelta::hours(1)) - .unwrap() - .timestamp(), - ) - .unwrap(); - - let signer = PrivateKeySigner::from_str(&env::var("ENS_SIGNER_PRIVATE_KEY").unwrap()).unwrap(); - - let data = GatewayResponse { - expires_at, - sender: sender.0, - response_hash: keccak256(&response), - request_hash: keccak256(request_data), - }; - - let domain = eip712_domain! { - name: "World App Usernames", - version: "1.0.0", - chain_id: 1, - verifying_contract: sender.0, - salt: keccak256(env::var("ENS_RESOLVER_SALT").unwrap()), - }; - - let signature = signer - .sign_typed_data(&data, &domain) - .await? - .inner() - .to_bytes() - .to_vec(); - - Ok(format!( - "0x{}", - hex::encode((response, expires_at, signature).abi_encode()) - )) + let expires_at = Uint::from_i64( + Utc::now() + .checked_add_signed(TimeDelta::hours(1)) + .unwrap() + .timestamp(), + ) + .unwrap(); + + let signer = AwsSigner::new(kms_client, config.kms_key_id.clone(), None).await?; + + let data = GatewayResponse { + expires_at, + sender: sender.0, + response_hash: keccak256(&response), + request_hash: keccak256(request_data), + }; + + let domain = eip712_domain! { + name: "World App Usernames", + version: "1.0.0", + chain_id: config.ens_chain_id, + verifying_contract: sender.0, + salt: config.ens_resolver_salt, + }; + + let signature = signer + .sign_typed_data(&data, &domain) + .await? + .inner() + .to_bytes() + .to_vec(); + + Ok(format!( + "0x{}", + hex::encode((response, expires_at, signature).abi_encode()) + )) } diff --git a/src/routes/api/v1/mod.rs b/src/routes/api/v1/mod.rs index a201685..bd37489 100644 --- a/src/routes/api/v1/mod.rs +++ b/src/routes/api/v1/mod.rs @@ -1,6 +1,6 @@ use aide::axum::{ - routing::{get_with, post_with}, - ApiRouter, + routing::{get_with, post_with}, + ApiRouter, }; mod ens_gateway; @@ -14,15 +14,15 @@ use query_single::{docs as query_single_docs, query_single}; use register_username::{docs as register_username_docs, register_username}; pub fn handler() -> ApiRouter { - ApiRouter::new() - .api_route("/ens", post_with(ens_gateway, ens_gateway_docs)) - .api_route("/query", post_with(query_multiple, query_multiple_docs)) - .api_route( - "/register", - post_with(register_username, register_username_docs), - ) - .api_route( - "/:name_or_address", - get_with(query_single, query_single_docs), - ) + ApiRouter::new() + .api_route("/ens", post_with(ens_gateway, ens_gateway_docs)) + .api_route("/query", post_with(query_multiple, query_multiple_docs)) + .api_route( + "/register", + post_with(register_username, register_username_docs), + ) + .api_route( + "/:name_or_address", + get_with(query_single, query_single_docs), + ) } diff --git a/src/routes/api/v1/query_multiple.rs b/src/routes/api/v1/query_multiple.rs index b2e1e82..48ffd9c 100644 --- a/src/routes/api/v1/query_multiple.rs +++ b/src/routes/api/v1/query_multiple.rs @@ -5,26 +5,26 @@ use sqlx::PgPool; use crate::types::{ErrorResponse, Name, QueryAddressesPayload, UsernameRecord}; pub async fn query_multiple( - Extension(db): Extension, - Json(payload): Json, + Extension(db): Extension, + Json(payload): Json, ) -> Result>, ErrorResponse> { - let addresses = payload - .addresses - .iter() - .map(|a| a.0.to_checksum(None)) - .collect::>(); + let addresses = payload + .addresses + .iter() + .map(|a| a.0.to_checksum(None)) + .collect::>(); - let names = sqlx::query_as!( - Name, - "SELECT * FROM names WHERE address = ANY($1)", - &addresses - ) - .fetch_all(&db) - .await?; + let names = sqlx::query_as!( + Name, + "SELECT * FROM names WHERE address = ANY($1)", + &addresses + ) + .fetch_all(&db) + .await?; - Ok(Json(names.into_iter().map(UsernameRecord::from).collect())) + Ok(Json(names.into_iter().map(UsernameRecord::from).collect())) } pub fn docs(op: aide::transform::TransformOperation) -> aide::transform::TransformOperation { - op.description("Resolve multiple addresses into their registered usernames.") + op.description("Resolve multiple addresses into their registered usernames.") } diff --git a/src/routes/api/v1/query_single.rs b/src/routes/api/v1/query_single.rs index e36ae83..036bc72 100644 --- a/src/routes/api/v1/query_single.rs +++ b/src/routes/api/v1/query_single.rs @@ -1,7 +1,7 @@ use axum::{ - extract::Path, - response::{IntoResponse, Redirect, Response}, - Extension, + extract::Path, + response::{IntoResponse, Redirect, Response}, + Extension, }; use axum_jsonschema::Json; use sqlx::PgPool; @@ -9,41 +9,41 @@ use sqlx::PgPool; use crate::types::{ErrorResponse, MovedRecord, Name, UsernameRecord}; pub async fn query_single( - Extension(db): Extension, - Path(name_or_address): Path, + Extension(db): Extension, + Path(name_or_address): Path, ) -> Result { - if let Some(name) = sqlx::query_as!( - Name, - "SELECT * FROM names WHERE username = $1 OR address = $1", - name_or_address - ) - .fetch_optional(&db) - .await? - { - return Ok(Json(UsernameRecord::from(name)).into_response()); - }; + if let Some(name) = sqlx::query_as!( + Name, + "SELECT * FROM names WHERE username = $1 OR address = $1", + name_or_address + ) + .fetch_optional(&db) + .await? + { + return Ok(Json(UsernameRecord::from(name)).into_response()); + }; - if let Some(moved) = sqlx::query_as!( - MovedRecord, - "SELECT * FROM old_names WHERE old_username = $1", - name_or_address - ) - .fetch_optional(&db) - .await? - { - return Ok(Redirect::permanent(&format!("/api/v1/{}", moved.new_username)).into_response()); - } + if let Some(moved) = sqlx::query_as!( + MovedRecord, + "SELECT * FROM old_names WHERE old_username = $1", + name_or_address + ) + .fetch_optional(&db) + .await? + { + return Ok(Redirect::permanent(&format!("/api/v1/{}", moved.new_username)).into_response()); + } - Err(ErrorResponse::not_found("Record not found.".to_string())) + Err(ErrorResponse::not_found("Record not found.".to_string())) } pub fn docs(op: aide::transform::TransformOperation) -> aide::transform::TransformOperation { - op.description("Resolve a single username or address.") - .response::<404, ErrorResponse>() - .response::<200, Json>() - .response_with::<301, Redirect, _>(|op| { - op.description( - "A redirect to the new username, if the queries username has recently changed.", - ) - }) + op.description("Resolve a single username or address.") + .response::<404, ErrorResponse>() + .response::<200, Json>() + .response_with::<301, Redirect, _>(|op| { + op.description( + "A redirect to the new username, if the queries username has recently changed.", + ) + }) } diff --git a/src/routes/api/v1/register_username.rs b/src/routes/api/v1/register_username.rs index 11ee78a..671f15c 100644 --- a/src/routes/api/v1/register_username.rs +++ b/src/routes/api/v1/register_username.rs @@ -1,65 +1,64 @@ use axum::Extension; use axum_jsonschema::Json; use http::StatusCode; -use idkit::session::{AppId, VerificationLevel}; +use idkit::session::VerificationLevel; use regex::Regex; use sqlx::PgPool; -use std::{ - env, - sync::{Arc, LazyLock}, -}; +use std::sync::LazyLock; use crate::{ - blocklist::Blocklist, - types::{ErrorResponse, Name, RegisterUsernamePayload}, + blocklist::BlocklistExt, + config::ConfigExt, + types::{ErrorResponse, Name, RegisterUsernamePayload}, }; static USERNAME_REGEX: LazyLock = - LazyLock::new(|| Regex::new(r"^[a-z]\w{2,13}[a-z0-9]$").unwrap()); + LazyLock::new(|| Regex::new(r"^[a-z]\w{2,13}[a-z0-9]$").unwrap()); static DEVICE_USERNAME_REGEX: LazyLock = - LazyLock::new(|| Regex::new(r"^[a-z]\w{2,13}[a-z0-9]\.\d{4}$").unwrap()); + LazyLock::new(|| Regex::new(r"^[a-z]\w{2,13}[a-z0-9]\.\d{4}$").unwrap()); #[allow(dependency_on_unit_never_type_fallback)] pub async fn register_username( - Extension(db): Extension, - Extension(blocklist): Extension>, - Json(payload): Json, + Extension(config): ConfigExt, + Extension(db): Extension, + Extension(blocklist): BlocklistExt, + Json(payload): Json, ) -> Result { - match idkit::verify_proof( - payload.into_proof(), - unsafe { AppId::new_unchecked(env::var("WORLD_ID_APP_ID").unwrap()) }, - "username", - (&payload.username, payload.address.0.to_checksum(None)), - ) - .await - { - Ok(()) => {} - Err(idkit::verify::Error::Verification(e)) => { - return Err(ErrorResponse::validation_error(e.detail)) - } - Err(_) => { - return Err(ErrorResponse::server_error( - "Failed to verify World ID proof".to_string(), - )) - } - }; + match idkit::verify_proof( + payload.into_proof(), + config.wld_app_id.clone(), + "username", + (&payload.username, payload.address.0.to_checksum(None)), + ) + .await + { + Ok(()) => {}, + Err(idkit::verify::Error::Verification(e)) => { + return Err(ErrorResponse::validation_error(e.detail)) + }, + Err(_) => { + return Err(ErrorResponse::server_error( + "Failed to verify World ID proof".to_string(), + )) + }, + }; - let username_regex = match payload.verification_level.0 { - VerificationLevel::Orb => USERNAME_REGEX.clone(), - VerificationLevel::Device => DEVICE_USERNAME_REGEX.clone(), - }; + let username_regex = match payload.verification_level.0 { + VerificationLevel::Orb => USERNAME_REGEX.clone(), + VerificationLevel::Device => DEVICE_USERNAME_REGEX.clone(), + }; - if !username_regex.is_match(&payload.username) { - return Err(ErrorResponse::validation_error( - "Username does not match the required pattern".to_string(), - )); - } + if !username_regex.is_match(&payload.username) { + return Err(ErrorResponse::validation_error( + "Username does not match the required pattern".to_string(), + )); + } - blocklist - .ensure_valid(&payload.username) - .map_err(|e| ErrorResponse::validation_error(e.to_string()))?; + blocklist + .ensure_valid(&payload.username) + .map_err(|e| ErrorResponse::validation_error(e.to_string()))?; - let uniqueness_check = sqlx::query!( + let uniqueness_check = sqlx::query!( "SELECT EXISTS(SELECT 1 FROM names WHERE nullifier_hash = $2) AS world_id, EXISTS(SELECT 1 FROM names WHERE username = $1 UNION SELECT 1 FROM old_names where old_username = $1) AS username", @@ -69,30 +68,30 @@ pub async fn register_username( .fetch_one(&db) .await?; - if uniqueness_check.username.unwrap_or_default() { - return Err(ErrorResponse::validation_error( - "Username is already taken".to_string(), - )); - }; + if uniqueness_check.username.unwrap_or_default() { + return Err(ErrorResponse::validation_error( + "Username is already taken".to_string(), + )); + }; - if uniqueness_check.world_id.unwrap_or_default() { - return Err(ErrorResponse::validation_error( - "This World ID has already registered a username.".to_string(), - )); - } + if uniqueness_check.world_id.unwrap_or_default() { + return Err(ErrorResponse::validation_error( + "This World ID has already registered a username.".to_string(), + )); + } - Name::new( - payload.username, - &payload.address, - payload.nullifier_hash, - &payload.verification_level, - ) - .insert(&db, "names") - .await?; + Name::new( + payload.username, + &payload.address, + payload.nullifier_hash, + &payload.verification_level, + ) + .insert(&db, "names") + .await?; - Ok(StatusCode::CREATED) + Ok(StatusCode::CREATED) } pub fn docs(op: aide::transform::TransformOperation) -> aide::transform::TransformOperation { - op.description("Register a World App username with World ID.") + op.description("Register a World App username with World ID.") } diff --git a/src/routes/docs.rs b/src/routes/docs.rs index c58a870..df7ac6f 100644 --- a/src/routes/docs.rs +++ b/src/routes/docs.rs @@ -2,14 +2,14 @@ use aide::{axum::ApiRouter, openapi::OpenApi, scalar::Scalar}; use axum::{routing::get, Extension, Json}; pub fn handler() -> ApiRouter { - let scalar = Scalar::new("/openapi.json").with_title("Orbit Docs"); + let scalar = Scalar::new("/openapi.json").with_title("Orbit Docs"); - ApiRouter::new() - .route("/docs", scalar.axum_route()) - .route("/openapi.json", get(openapi_schema)) + ApiRouter::new() + .route("/docs", scalar.axum_route()) + .route("/openapi.json", get(openapi_schema)) } #[allow(clippy::unused_async)] async fn openapi_schema(Extension(openapi): Extension) -> Json { - Json(openapi) + Json(openapi) } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 3f12d8a..db56b06 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -5,8 +5,8 @@ mod docs; mod system; pub fn handler() -> ApiRouter { - ApiRouter::new() - .merge(docs::handler()) - .merge(system::handler()) - .nest("/api", api::handler()) + ApiRouter::new() + .merge(docs::handler()) + .merge(system::handler()) + .nest("/api", api::handler()) } diff --git a/src/routes/system.rs b/src/routes/system.rs index 5edba2a..b38dc3c 100644 --- a/src/routes/system.rs +++ b/src/routes/system.rs @@ -3,38 +3,38 @@ use axum_jsonschema::Json; use schemars::JsonSchema; pub fn handler() -> ApiRouter { - ApiRouter::new().api_route("/", get(root)) + ApiRouter::new().api_route("/", get(root)) } #[derive(Debug, serde::Serialize, JsonSchema)] pub struct AppVersion { - /// Current version of the application - semver: String, - /// Commit hash of the current build (if available) - rev: Option, - /// The time the application was compiled at - compile_time: String, + /// Current version of the application + semver: String, + /// Commit hash of the current build (if available) + rev: Option, + /// The time the application was compiled at + compile_time: String, } #[derive(Debug, serde::Serialize, JsonSchema)] pub struct RootResponse { - /// Relative URL to Swagger UI - pub docs_url: String, - /// Relative URL to `OpenAPI` specification - pub openapi_url: String, - /// Application version - pub version: AppVersion, + /// Relative URL to Swagger UI + pub docs_url: String, + /// Relative URL to `OpenAPI` specification + pub openapi_url: String, + /// Application version + pub version: AppVersion, } #[allow(clippy::unused_async)] pub async fn root() -> Json { - Json(RootResponse { - docs_url: "/docs".to_string(), - openapi_url: "/openapi.json".to_string(), - version: AppVersion { - semver: env!("CARGO_PKG_VERSION").to_string(), - compile_time: env!("STATIC_BUILD_DATE").to_string(), - rev: option_env!("GIT_REV").map(ToString::to_string), - }, - }) + Json(RootResponse { + docs_url: "/docs".to_string(), + openapi_url: "/openapi.json".to_string(), + version: AppVersion { + semver: env!("CARGO_PKG_VERSION").to_string(), + compile_time: env!("STATIC_BUILD_DATE").to_string(), + rev: option_env!("GIT_REV").map(ToString::to_string), + }, + }) } diff --git a/src/server.rs b/src/server.rs index b9d6c35..26f8a24 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,63 +1,64 @@ use aide::openapi::{self, OpenApi}; use anyhow::Result; use axum::Extension; -use sqlx::PgPool; use std::{env, net::SocketAddr}; use tokio::{net::TcpListener, signal}; -use crate::{blocklist::Blocklist, routes}; - -pub async fn start(postgres: PgPool, blocklist: Blocklist) -> Result<()> { - let mut openapi = OpenApi { - info: openapi::Info { - title: "World App Username API".to_string(), - version: env!("CARGO_PKG_VERSION").to_string(), - ..openapi::Info::default() - }, - ..OpenApi::default() - }; - - let router = routes::handler() - .finish_api(&mut openapi) - .layer(Extension(openapi)) - .layer(Extension(postgres)) - .layer(blocklist.extension()); - - let addr = SocketAddr::from(( - [0, 0, 0, 0], - env::var("PORT").map_or(Ok(8000), |p| p.parse())?, - )); - let listener = TcpListener::bind(&addr).await?; - - tracing::info!("Starting server on {addr}..."); - - axum::serve(listener, router.into_make_service()) - .with_graceful_shutdown(shutdown_signal()) - .await?; - - Ok(()) +use crate::{config::Config, routes}; + +pub async fn start(mut config: Config) -> Result<()> { + let mut openapi = OpenApi { + info: openapi::Info { + title: "World App Username API".to_string(), + version: env!("CARGO_PKG_VERSION").to_string(), + ..openapi::Info::default() + }, + ..OpenApi::default() + }; + + let router = routes::handler() + .finish_api(&mut openapi) + .layer(Extension(openapi)) + .layer(config.db_extension()) + .layer(config.kms_extension()) + .layer(config.blocklist_extension()) + .layer(config.extension()); + + let addr = SocketAddr::from(( + [0, 0, 0, 0], + env::var("PORT").map_or(Ok(8000), |p| p.parse())?, + )); + let listener = TcpListener::bind(&addr).await?; + + tracing::info!("Starting server on {addr}..."); + + axum::serve(listener, router.into_make_service()) + .with_graceful_shutdown(shutdown_signal()) + .await?; + + Ok(()) } async fn shutdown_signal() { - let ctrl_c = async { - signal::ctrl_c() - .await - .expect("failed to install Ctrl+C handler"); - }; - - #[cfg(unix)] - let terminate = async { - signal::unix::signal(signal::unix::SignalKind::terminate()) - .expect("failed to install signal handler") - .recv() - .await; - }; - - #[cfg(not(unix))] - let terminate = std::future::pending::<()>(); - - tokio::select! { - () = ctrl_c => {}, - () = terminate => {}, - } + let ctrl_c = async { + signal::ctrl_c() + .await + .expect("failed to install Ctrl+C handler"); + }; + + #[cfg(unix)] + let terminate = async { + signal::unix::signal(signal::unix::SignalKind::terminate()) + .expect("failed to install signal handler") + .recv() + .await; + }; + + #[cfg(not(unix))] + let terminate = std::future::pending::<()>(); + + tokio::select! { + () = ctrl_c => {}, + () = terminate => {}, + } } diff --git a/src/types/database.rs b/src/types/database.rs index d80f61a..5978846 100644 --- a/src/types/database.rs +++ b/src/types/database.rs @@ -6,42 +6,42 @@ use sqlxinsert::PgInsert; /// A registered username. #[derive(Debug, FromRow, PgInsert)] pub struct Name { - /// Checksummed address of the owner. - pub address: String, - /// World App username of the owner. - pub username: String, - /// The nullifier hash of the proof that was used to register this name. - pub nullifier_hash: String, - /// The verificaiton level of the proof that was used to register this name. - pub verification_level: String, - /// The time at which this name was registered. - pub created_at: chrono::NaiveDateTime, - /// The time at which this name was last updated. - pub updated_at: chrono::NaiveDateTime, + /// Checksummed address of the owner. + pub address: String, + /// World App username of the owner. + pub username: String, + /// The nullifier hash of the proof that was used to register this name. + pub nullifier_hash: String, + /// The verificaiton level of the proof that was used to register this name. + pub verification_level: String, + /// The time at which this name was registered. + pub created_at: chrono::NaiveDateTime, + /// The time at which this name was last updated. + pub updated_at: chrono::NaiveDateTime, } impl Name { - pub fn new( - username: String, - address: &Address, - nullifier_hash: String, - verification_level: &VerificationLevel, - ) -> Self { - Self { - username, - nullifier_hash, - created_at: Utc::now().naive_utc(), - updated_at: Utc::now().naive_utc(), - address: address.0.to_checksum(None), - verification_level: verification_level.to_string(), - } - } + pub fn new( + username: String, + address: &Address, + nullifier_hash: String, + verification_level: &VerificationLevel, + ) -> Self { + Self { + username, + nullifier_hash, + created_at: Utc::now().naive_utc(), + updated_at: Utc::now().naive_utc(), + address: address.0.to_checksum(None), + verification_level: verification_level.to_string(), + } + } } #[allow(dead_code)] #[derive(Debug, FromRow, PgInsert)] pub struct MovedRecord { - pub id: f64, - pub old_username: String, - pub new_username: String, + pub id: f64, + pub old_username: String, + pub new_username: String, } diff --git a/src/types/ens.rs b/src/types/ens.rs index 1c0181d..2bd1124 100644 --- a/src/types/ens.rs +++ b/src/types/ens.rs @@ -1,63 +1,65 @@ #![allow(clippy::pub_underscore_fields)] -use alloy_sol_types::{sol, SolCall}; +use alloy::sol_types::{sol, SolCall}; use anyhow::bail; use std::string::FromUtf8Error; use crate::utils::decode_ens_name; sol! { - function resolve( - bytes calldata name, - bytes calldata data - ); - - function addr(bytes32 node) returns (address); - function text(bytes32 node, string key) returns (string); - - struct GatewayResponse { - address sender; - uint256 expires_at; - bytes32 request_hash; - bytes32 response_hash; - } + #![sol(alloy_sol_types = ::alloy::sol_types)] + + function resolve( + bytes calldata name, + bytes calldata data + ); + + function addr(bytes32 node) returns (address); + function text(bytes32 node, string key) returns (string); + + struct GatewayResponse { + address sender; + uint256 expires_at; + bytes32 request_hash; + bytes32 response_hash; + } } pub enum Method { - Abi, - Name, - PubKey, - ContentHash, - Addr(Vec), - AddrMultichain, - InterfaceImplementer, - Text(Vec, String), + Abi, + Name, + PubKey, + ContentHash, + Addr(Vec), + AddrMultichain, + InterfaceImplementer, + Text(Vec, String), } impl resolveCall { - pub fn parse_name(&self) -> Result { - Ok(decode_ens_name(&String::from_utf8(self.name.to_vec())?)) - } - - pub fn parse_method(&self) -> anyhow::Result { - let method = match hex::encode(&self.data[..4]).as_str() { - "2203ab56" => Method::Abi, - "691f3431" => Method::Name, - "c8690233" => Method::PubKey, - "bc1c58d1" => Method::ContentHash, - "f1cb7e06" => Method::AddrMultichain, - "b8f2bbb4" => Method::InterfaceImplementer, - "3b3b57de" => { - let addr = addrCall::abi_decode(&self.data, true)?; - Method::Addr(addr.node.to_vec()) - } - "59d1d43c" => { - let addr = textCall::abi_decode(&self.data, true)?; - Method::Text(addr.node.to_vec(), addr.key) - } - _ => bail!("invalid method"), - }; - - Ok(method) - } + pub fn parse_name(&self) -> Result { + Ok(decode_ens_name(&String::from_utf8(self.name.to_vec())?)) + } + + pub fn parse_method(&self) -> anyhow::Result { + let method = match hex::encode(&self.data[..4]).as_str() { + "2203ab56" => Method::Abi, + "691f3431" => Method::Name, + "c8690233" => Method::PubKey, + "bc1c58d1" => Method::ContentHash, + "f1cb7e06" => Method::AddrMultichain, + "b8f2bbb4" => Method::InterfaceImplementer, + "3b3b57de" => { + let addr = addrCall::abi_decode(&self.data, true)?; + Method::Addr(addr.node.to_vec()) + }, + "59d1d43c" => { + let addr = textCall::abi_decode(&self.data, true)?; + Method::Text(addr.node.to_vec(), addr.key) + }, + _ => bail!("invalid method"), + }; + + Ok(method) + } } diff --git a/src/types/error.rs b/src/types/error.rs index 94cb808..437ff11 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -9,99 +9,99 @@ use serde::{Deserialize, Serialize}; #[derive(Debug)] pub struct ErrorResponse { - error: String, - status: StatusCode, + error: String, + status: StatusCode, } #[derive(Debug, Serialize, JsonSchema)] struct ErrorResponseSchema { - error: String, + error: String, } impl ErrorResponse { - pub const fn not_found(error: String) -> Self { - Self { - error, - status: StatusCode::NOT_FOUND, - } - } - - pub const fn validation_error(error: String) -> Self { - Self { - error, - status: StatusCode::UNPROCESSABLE_ENTITY, - } - } - - pub const fn server_error(error: String) -> Self { - Self { - error, - status: StatusCode::INTERNAL_SERVER_ERROR, - } - } + pub const fn not_found(error: String) -> Self { + Self { + error, + status: StatusCode::NOT_FOUND, + } + } + + pub const fn validation_error(error: String) -> Self { + Self { + error, + status: StatusCode::UNPROCESSABLE_ENTITY, + } + } + + pub const fn server_error(error: String) -> Self { + Self { + error, + status: StatusCode::INTERNAL_SERVER_ERROR, + } + } } impl From for ErrorResponse { - fn from(err: E) -> Self { - tracing::error!(err = ?err); + fn from(err: E) -> Self { + tracing::error!(err = ?err); - Self::server_error("Internal Server Error".to_string()) - } + Self::server_error("Internal Server Error".to_string()) + } } impl IntoResponse for ErrorResponse { - fn into_response(self) -> axum::response::Response { - (self.status, Json(ErrorResponseSchema { error: self.error })).into_response() - } + fn into_response(self) -> axum::response::Response { + (self.status, Json(ErrorResponseSchema { error: self.error })).into_response() + } } impl OperationOutput for ErrorResponse { - type Inner = Self; - - fn operation_response( - ctx: &mut aide::gen::GenContext, - operation: &mut aide::openapi::Operation, - ) -> Option { - Json::::operation_response(ctx, operation) - } + type Inner = Self; + + fn operation_response( + ctx: &mut aide::gen::GenContext, + operation: &mut aide::openapi::Operation, + ) -> Option { + Json::::operation_response(ctx, operation) + } } #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct ENSErrorResponse { - /// A human-readable error message. - pub message: String, + /// A human-readable error message. + pub message: String, } impl ENSErrorResponse { - pub fn new(message: &str) -> Self { - Self { - message: message.to_string(), - } - } + pub fn new(message: &str) -> Self { + Self { + message: message.to_string(), + } + } } impl IntoResponse for ENSErrorResponse { - fn into_response(self) -> axum::response::Response { - (StatusCode::BAD_REQUEST, Json(self)).into_response() - } + fn into_response(self) -> axum::response::Response { + (StatusCode::BAD_REQUEST, Json(self)).into_response() + } } impl OperationOutput for ENSErrorResponse { - type Inner = Self; - - fn operation_response( - ctx: &mut GenContext, - operation: &mut Operation, - ) -> Option { - Json::::operation_response(ctx, operation) - } - - fn inferred_responses( - ctx: &mut aide::gen::GenContext, - operation: &mut Operation, - ) -> Vec<(Option, aide::openapi::Response)> { - Self::operation_response(ctx, operation).map_or_else(Vec::new, |res| { - vec![(Some(StatusCode::BAD_REQUEST.as_u16()), res)] - }) - } + type Inner = Self; + + fn operation_response( + ctx: &mut GenContext, + operation: &mut Operation, + ) -> Option { + Json::::operation_response(ctx, operation) + } + + fn inferred_responses( + ctx: &mut aide::gen::GenContext, + operation: &mut Operation, + ) -> Vec<(Option, aide::openapi::Response)> { + Self::operation_response(ctx, operation).map_or_else(Vec::new, |res| { + vec![(Some(StatusCode::BAD_REQUEST.as_u16()), res)] + }) + } } diff --git a/src/types/request.rs b/src/types/request.rs index 75264f5..c4f5a2c 100644 --- a/src/types/request.rs +++ b/src/types/request.rs @@ -6,40 +6,40 @@ use super::{Address, VerificationLevel}; #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct RegisterUsernamePayload { - /// 0x-prefixed hex string of the World ID proof. - proof: String, - /// 0x-prefixed hex string of the World ID merkle root. - merkle_root: String, - /// The requested username. - pub username: String, - /// The user's walle address. - pub address: Address, - /// 0x-prefixed hex string of the World ID nullifier hash. - pub nullifier_hash: String, - /// World ID verification level the user holds. - pub verification_level: VerificationLevel, + /// 0x-prefixed hex string of the World ID proof. + proof: String, + /// 0x-prefixed hex string of the World ID merkle root. + merkle_root: String, + /// The requested username. + pub username: String, + /// The user's walle address. + pub address: Address, + /// 0x-prefixed hex string of the World ID nullifier hash. + pub nullifier_hash: String, + /// World ID verification level the user holds. + pub verification_level: VerificationLevel, } impl RegisterUsernamePayload { - #[allow(clippy::wrong_self_convention)] - pub fn into_proof(&self) -> Proof { - Proof { - proof: self.proof.clone(), - merkle_root: self.merkle_root.clone(), - nullifier_hash: self.nullifier_hash.clone(), - verification_level: self.verification_level.0, - } - } + #[allow(clippy::wrong_self_convention)] + pub fn into_proof(&self) -> Proof { + Proof { + proof: self.proof.clone(), + merkle_root: self.merkle_root.clone(), + nullifier_hash: self.nullifier_hash.clone(), + verification_level: self.verification_level.0, + } + } } #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct QueryAddressesPayload { - /// A list of addresses to resolve. - pub addresses: Vec
, + /// A list of addresses to resolve. + pub addresses: Vec
, } #[derive(Debug, Deserialize, JsonSchema)] pub struct ENSQueryPayload { - pub data: String, - pub sender: Address, + pub data: String, + pub sender: Address, } diff --git a/src/types/response.rs b/src/types/response.rs index 629886d..19c4fb5 100644 --- a/src/types/response.rs +++ b/src/types/response.rs @@ -8,24 +8,24 @@ use super::{Address, Name}; #[derive(Debug, Serialize, Deserialize, JsonSchema, OperationIo)] pub struct ENSResponse { - /// 0x-prefixed hex string containing the result data. - pub data: String, + /// 0x-prefixed hex string containing the result data. + pub data: String, } #[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct UsernameRecord { - /// The user's World App username. - pub username: String, - /// Checksummed wallet address of the user. - pub address: Address, + /// The user's World App username. + pub username: String, + /// Checksummed wallet address of the user. + pub address: Address, } #[allow(clippy::fallible_impl_from)] impl From for UsernameRecord { - fn from(value: Name) -> Self { - Self { - username: value.username, - address: Address(value.address.parse().unwrap()), - } - } + fn from(value: Name) -> Self { + Self { + username: value.username, + address: Address(value.address.parse().unwrap()), + } + } } diff --git a/src/types/wrappers.rs b/src/types/wrappers.rs index b6d889d..469d373 100644 --- a/src/types/wrappers.rs +++ b/src/types/wrappers.rs @@ -1,40 +1,38 @@ -use schemars::schema; -use schemars::JsonSchema; +use schemars::{schema, JsonSchema}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::fmt; -use std::{fmt::Display, ops::Deref}; +use std::{fmt, fmt::Display, ops::Deref}; /// 0x-prefixed hex string representing an Ethereum address. #[repr(transparent)] #[derive(Debug, Serialize, Deserialize)] -pub struct Address(pub alloy_primitives::Address); +pub struct Address(pub alloy::primitives::Address); impl Deref for Address { - type Target = alloy_primitives::Address; + type Target = alloy::primitives::Address; - fn deref(&self) -> &Self::Target { - &self.0 - } + fn deref(&self) -> &Self::Target { + &self.0 + } } impl JsonSchema for Address { - fn schema_name() -> String { - "Address".to_string() - } + fn schema_name() -> String { + "Address".to_string() + } - fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schema::Schema { - schema::Schema::Object(schema::SchemaObject { - string: Some(Box::new(schema::StringValidation { - pattern: Some("^0x[a-fA-F0-9]{40}$".to_string()), - ..Default::default() - })), - instance_type: Some(schema::SingleOrVec::Single(Box::new( - schema::InstanceType::String, - ))), - ..Default::default() - }) - } + fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schema::Schema { + schema::Schema::Object(schema::SchemaObject { + string: Some(Box::new(schema::StringValidation { + pattern: Some("^0x[a-fA-F0-9]{40}$".to_string()), + ..Default::default() + })), + instance_type: Some(schema::SingleOrVec::Single(Box::new( + schema::InstanceType::String, + ))), + ..Default::default() + }) + } } /// World ID verification level @@ -43,26 +41,26 @@ impl JsonSchema for Address { pub struct VerificationLevel(pub idkit::session::VerificationLevel); impl Display for VerificationLevel { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - self.0.fmt(f) - } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } } impl JsonSchema for VerificationLevel { - fn schema_name() -> String { - "VerificationLevel".to_string() - } + fn schema_name() -> String { + "VerificationLevel".to_string() + } - fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schema::Schema { - schema::Schema::Object(schema::SchemaObject { - enum_values: Some(vec![ - Value::String("orb".to_string()), - Value::String("device".to_string()), - ]), - instance_type: Some(schema::SingleOrVec::Single(Box::new( - schema::InstanceType::String, - ))), - ..Default::default() - }) - } + fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schema::Schema { + schema::Schema::Object(schema::SchemaObject { + enum_values: Some(vec![ + Value::String("orb".to_string()), + Value::String("device".to_string()), + ]), + instance_type: Some(schema::SingleOrVec::Single(Box::new( + schema::InstanceType::String, + ))), + ..Default::default() + }) + } } diff --git a/src/utils.rs b/src/utils.rs index b212078..ace0cbf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,30 +1,30 @@ -use alloy_primitives::keccak256; +use alloy::primitives::keccak256; pub fn namehash(name: &str) -> [u8; 32] { - if name.is_empty() { - return [0; 32]; - } + if name.is_empty() { + return [0; 32]; + } - // Remove the variation selector U+FE0F - let name = name.replace('\u{fe0f}', ""); + // Remove the variation selector U+FE0F + let name = name.replace('\u{fe0f}', ""); - // Generate the node starting from the right - name.rsplit('.').fold([0u8; 32], |node, label| { - *keccak256([node, *keccak256(label.as_bytes())].concat()) - }) + // Generate the node starting from the right + name.rsplit('.').fold([0u8; 32], |node, label| { + *keccak256([node, *keccak256(label.as_bytes())].concat()) + }) } pub fn decode_ens_name(name: &str) -> String { - let mut labels: Vec<&str> = Vec::new(); - let mut idx = 0; - loop { - let len = name.as_bytes()[idx] as usize; - if len == 0 { - break; - } - labels.push(&name[(idx + 1)..=(idx + len)]); - idx += len + 1; - } + let mut labels: Vec<&str> = Vec::new(); + let mut idx = 0; + loop { + let len = name.as_bytes()[idx] as usize; + if len == 0 { + break; + } + labels.push(&name[(idx + 1)..=(idx + len)]); + idx += len + 1; + } - labels.join(".") + labels.join(".") }