From 6a9a5a30c87e73f3314f3878897e0e0e81f58ed6 Mon Sep 17 00:00:00 2001 From: Ashton Stephens Date: Thu, 2 May 2024 08:23:44 -0400 Subject: [PATCH] Emily Rust Lambda Boilerplate (#101) * Add NotImplementedError to Smithy API definition. * Create rust lambda boilerplace. * Fix CI by forcing autogenerated sources to be made before cargo test. * Remove incorrect comments. * remove unnecessary unused_extern_crates flag. * Address style changes and link TODO ticket * Move main to be the first function in the lambda. --- .github/workflows/rust-tests.yaml | 4 + Cargo.lock | 1066 ++++++++++++++++- Cargo.toml | 14 + .../models/chainstate/ops.smithy | 3 + .../api-definition/models/deposits/ops.smithy | 5 + emily/api-definition/models/errors.smithy | 7 + .../models/withdrawals/ops.smithy | 4 + emily/lambda/Cargo.toml | 19 + emily/lambda/src/main.rs | 177 +++ 9 files changed, 1276 insertions(+), 23 deletions(-) create mode 100644 emily/lambda/Cargo.toml create mode 100644 emily/lambda/src/main.rs diff --git a/.github/workflows/rust-tests.yaml b/.github/workflows/rust-tests.yaml index 1c97c039..3d7f5618 100644 --- a/.github/workflows/rust-tests.yaml +++ b/.github/workflows/rust-tests.yaml @@ -29,4 +29,8 @@ jobs: - uses: Swatinem/rust-cache@v2 + # Build Emily first so that the autogenerated `lib.rs` file is + # present when building the rest of the crates in the workspace. + - run: cargo build --package emily + - run: cargo test diff --git a/Cargo.lock b/Cargo.lock index 4aa4b956..b7f33dab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,54 +26,255 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +[[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 1.1.8", + "zeroize", +] + +[[package]] +name = "aws-runtime" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4963ac9ff2d33a4231b3806c1c69f578f221a9cabb89ad2bde62ce2b442c8a7" +dependencies = [ + "aws-credential-types", + "aws-sigv4 1.2.1", + "aws-smithy-async", + "aws-smithy-http 0.60.8", + "aws-smithy-runtime-api", + "aws-smithy-types 1.1.8", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "http-body 0.4.6", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-dynamodb" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059a3cf6c50bc79b05153a18563be062f55a8b7b3e73392aec7ba479f825fc97" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http 0.60.8", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types 1.1.8", + "aws-types", + "bytes", + "fastrand", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + [[package]] name = "aws-sigv4" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2d486e1bc89b62a50ab74a6c626aa6e34923e4afdd12be26b4d173bb68a4d66" dependencies = [ - "aws-smithy-http", + "aws-smithy-http 0.33.1", "form_urlencoded", "hex", - "http", + "http 0.2.12", "once_cell", "percent-encoding", "regex", - "ring", + "ring 0.16.20", + "time", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b56f1cbe6fd4d0c2573df72868f20ab1c125ca9c9dbce17927a463433a2e57" +dependencies = [ + "aws-credential-types", + "aws-smithy-http 0.60.8", + "aws-smithy-runtime-api", + "aws-smithy-types 1.1.8", + "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.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a4b8e568f284def4d1edfb0705e7058928f355ae264c44359b80f021e24d419" dependencies = [ - "aws-smithy-types", + "aws-smithy-types 0.33.1", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", "percent-encoding", "pin-project", "tracing", ] +[[package]] +name = "aws-smithy-http" +version = "0.60.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a7de001a1b9a25601016d8057ea16e31a45fdca3751304c8edf4ad72e706c08" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types 1.1.8", + "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 1.1.8", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cf64e73ef8d4dac6c933230d56d136b75b252edcf82ed36e37d603090cd7348" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http 0.60.8", + "aws-smithy-runtime-api", + "aws-smithy-types 1.1.8", + "bytes", + "fastrand", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.0", + "hyper 0.14.28", + "hyper-rustls", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c19fdae6e3d5ac9cd01f2d6e6c359c5f5a3e028c2d148a8f5b90bf3399a18a7" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types 1.1.8", + "bytes", + "http 0.2.12", + "http 1.1.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + [[package]] name = "aws-smithy-types" version = "0.33.1" @@ -86,6 +287,67 @@ dependencies = [ "time", ] +[[package]] +name = "aws-smithy-types" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe14dceea1e70101d38fbf2a99e6a34159477c0fb95e68e05c66bd7ae4c3729" +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.0", + "http-body-util", + "itoa 1.0.11", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-types" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a43b56df2c529fe44cb4d92bd64d0479883fb9608ff62daede4df5405381814" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types 1.1.8", + "http 0.2.12", + "rustc_version", + "tracing", +] + +[[package]] +name = "aws_lambda_events" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598e2ade8447dce8d3a15b6159b73354db34257851344b232fb1920c272acc61" +dependencies = [ + "base64 0.21.7", + "bytes", + "chrono", + "flate2", + "http 1.1.0", + "http-body 1.0.0", + "http-serde", + "query_map", + "serde", + "serde_dynamo", + "serde_json", + "serde_with", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -117,6 +379,22 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +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 = "bech32" version = "0.11.0" @@ -183,6 +461,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -194,6 +481,9 @@ name = "bytes" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] [[package]] name = "bytes-utils" @@ -217,6 +507,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.5", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -233,6 +536,69 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.3.11" @@ -240,6 +606,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", ] [[package]] @@ -252,8 +630,8 @@ checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" name = "emily" version = "0.1.0" dependencies = [ - "aws-sigv4", - "http", + "aws-sigv4 0.3.1", + "http 0.2.12", "reqwest", "secrecy", "serde", @@ -263,6 +641,23 @@ dependencies = [ "uuid", ] +[[package]] +name = "emily-operation-lambda" +version = "0.1.0" +dependencies = [ + "aws-sdk-dynamodb", + "aws_lambda_events", + "emily", + "http 1.1.0", + "lambda_runtime", + "more-asserts", + "openssl", + "serde", + "serde_json", + "test-case", + "tokio", +] + [[package]] name = "encoding_rs" version = "0.8.34" @@ -294,6 +689,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -324,6 +729,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -331,6 +751,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -339,6 +760,34 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -357,10 +806,26 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", ] [[package]] @@ -391,20 +856,32 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", - "indexmap", + "http 0.2.12", + "indexmap 2.2.6", "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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" @@ -426,6 +903,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.12" @@ -437,6 +923,17 @@ dependencies = [ "itoa 1.0.11", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.11", +] + [[package]] name = "http-body" version = "0.4.6" @@ -444,10 +941,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] +[[package]] +name = "http-serde" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1133cafcce27ea69d35e56b3a8772e265633e04de73c5f4e1afdffc1d19b5419" +dependencies = [ + "http 1.1.0", + "serde", +] + [[package]] name = "httparse" version = "1.8.0" @@ -471,8 +1001,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa 1.0.11", @@ -484,6 +1014,41 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa 1.0.11", + "pin-project-lite", + "smallvec", + "tokio", + "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.28", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -491,12 +1056,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -507,6 +1121,17 @@ dependencies = [ "unicode-normalization", ] +[[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", + "serde", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -514,7 +1139,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", + "serde", ] [[package]] @@ -544,6 +1170,55 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lambda_runtime" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276c835f2217fac810a97f2ed8eabfe9be71afe4f3ffd8671b05cb528e95ff8a" +dependencies = [ + "async-stream", + "base64 0.21.7", + "bytes", + "futures", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "http-serde", + "hyper 1.3.1", + "hyper-util", + "lambda_runtime_api_client", + "pin-project", + "serde", + "serde_json", + "serde_path_to_error", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tracing", +] + +[[package]] +name = "lambda_runtime_api_client" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "722b02764422524d3f49a934b570f7c567f811eda1f9c4bdebebcfae1bad4f23" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "tokio", + "tower", + "tower-service", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -562,6 +1237,16 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.21" @@ -667,6 +1352,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "object" version = "0.32.2" @@ -714,6 +1409,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-src" +version = "300.2.3+3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.102" @@ -722,10 +1426,40 @@ checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -785,6 +1519,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "query_map" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eab6b8b1074ef3359a863758dae650c7c0c6027927a085b7af911c8e0bf3a15" +dependencies = [ + "form_urlencoded", + "serde", + "serde_derive", +] + [[package]] name = "quote" version = "1.0.36" @@ -794,6 +1539,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "regex" version = "1.10.4" @@ -826,6 +1580,12 @@ dependencies = [ "regex-syntax 0.8.3", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -844,15 +1604,15 @@ version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-tls", "ipnet", "js-sys", @@ -888,18 +1648,42 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.34" @@ -913,13 +1697,47 @@ 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 0.17.8", + "rustls-webpki", + "sct", +] + +[[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", + "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", + "base64 0.21.7", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -950,6 +1768,22 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + [[package]] name = "secp256k1" version = "0.29.0" @@ -1001,6 +1835,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + [[package]] name = "serde" version = "1.0.198" @@ -1021,6 +1861,16 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_dynamo" +version = "4.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36c1b1792cfd9de29eb373ee6a4b74650369c096f55db7198ceb7b8921d1f7f" +dependencies = [ + "base64 0.21.7", + "serde", +] + [[package]] name = "serde_json" version = "1.0.116" @@ -1032,6 +1882,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa 1.0.11", + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1044,6 +1904,47 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1053,6 +1954,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -1062,6 +1972,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "socket2" version = "0.5.7" @@ -1078,6 +1994,24 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "2.0.60" @@ -1247,11 +2181,26 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -1262,6 +2211,27 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -1276,6 +2246,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -1288,6 +2280,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1349,6 +2342,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicase" version = "2.7.0" @@ -1385,6 +2384,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -1424,6 +2429,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "want" version = "0.3.1" @@ -1537,6 +2548,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 1948c594..b330126c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "signer", ".generated-sources/emily", + "emily/lambda" ] [profile.dev] @@ -13,3 +14,16 @@ debug = 0 [profile.release] lto = "thin" codegen-units = 16 + +[workspace.dependencies] +emily = { version = "0.1.0", path = ".generated-sources/emily" } +tokio = "1.32.0" +serde = "1.0" +serde_json = "1.0" +lambda_runtime = "0.11.1" +aws_lambda_events = "0.15.0" +http = "1.1.0" +aws-sdk-dynamodb = { version = "1.3.0" } +futures = "0.3.24" +# This is necessary to compile the AWS Lambda as a lambda. +openssl = { version = "0.10", features = ["vendored"] } diff --git a/emily/api-definition/models/chainstate/ops.smithy b/emily/api-definition/models/chainstate/ops.smithy index fac9cc3e..4c0322f7 100644 --- a/emily/api-definition/models/chainstate/ops.smithy +++ b/emily/api-definition/models/chainstate/ops.smithy @@ -12,6 +12,7 @@ operation CreateChainstate { ThrottlingError ConflictError ForbiddenError + NotImplementedError ] } @@ -32,6 +33,7 @@ operation GetChainstate { ServiceError ThrottlingError NotFoundError + NotImplementedError ] } @@ -46,6 +48,7 @@ operation UpdateChainstate { NotFoundError ConflictError ForbiddenError + NotImplementedError ] } diff --git a/emily/api-definition/models/deposits/ops.smithy b/emily/api-definition/models/deposits/ops.smithy index 1e1347ed..dda492a7 100644 --- a/emily/api-definition/models/deposits/ops.smithy +++ b/emily/api-definition/models/deposits/ops.smithy @@ -11,6 +11,7 @@ operation CreateDeposit { ServiceError ThrottlingError ConflictError + NotImplementedError ] } @@ -34,6 +35,7 @@ operation GetDeposit { ServiceError ThrottlingError NotFoundError + NotImplementedError ] } @@ -52,6 +54,7 @@ operation GetTxnDeposits { ServiceError ThrottlingError NotFoundError + NotImplementedError ] } @@ -83,6 +86,7 @@ operation GetDeposits { ServiceError ThrottlingError NotFoundError + NotImplementedError ] } @@ -110,6 +114,7 @@ operation UpdateDeposits { NotFoundError ConflictError ForbiddenError + NotImplementedError ] } diff --git a/emily/api-definition/models/errors.smithy b/emily/api-definition/models/errors.smithy index 790c2412..8263ecee 100644 --- a/emily/api-definition/models/errors.smithy +++ b/emily/api-definition/models/errors.smithy @@ -37,3 +37,10 @@ structure ServiceError { @required message: String } + +@error("server") +@httpError(501) +structure NotImplementedError { + @required + message: String +} diff --git a/emily/api-definition/models/withdrawals/ops.smithy b/emily/api-definition/models/withdrawals/ops.smithy index 43734a53..578fa389 100644 --- a/emily/api-definition/models/withdrawals/ops.smithy +++ b/emily/api-definition/models/withdrawals/ops.smithy @@ -11,6 +11,7 @@ operation CreateWithdrawal { ServiceError ThrottlingError ConflictError + NotImplementedError ] } @@ -35,6 +36,7 @@ operation GetWithdrawal { ServiceError ThrottlingError NotFoundError + NotImplementedError ] } @@ -53,6 +55,7 @@ operation GetWithdrawals { ServiceError ThrottlingError NotFoundError + NotImplementedError ] } @@ -80,6 +83,7 @@ operation UpdateWithdrawals { NotFoundError ConflictError ForbiddenError + NotImplementedError ] } diff --git a/emily/lambda/Cargo.toml b/emily/lambda/Cargo.toml new file mode 100644 index 00000000..e71c9e43 --- /dev/null +++ b/emily/lambda/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "emily-operation-lambda" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = { workspace = true, features = ["full"] } +serde.workspace = true +serde_json.workspace = true +lambda_runtime.workspace = true +aws_lambda_events.workspace = true +http.workspace = true +aws-sdk-dynamodb.workspace = true +emily.workspace = true +openssl.workspace = true + +[dev-dependencies] +more-asserts = "0.3" +test-case = "3.1" diff --git a/emily/lambda/src/main.rs b/emily/lambda/src/main.rs new file mode 100644 index 00000000..ad0e95c7 --- /dev/null +++ b/emily/lambda/src/main.rs @@ -0,0 +1,177 @@ +use aws_lambda_events::apigw::{ApiGatewayProxyRequest, ApiGatewayProxyResponse}; +use aws_lambda_events::encodings::Body; +use emily::models::{CreateDepositRequestContent, DepositParameters}; +use http::{header, HeaderValue}; +use lambda_runtime::{service_fn, LambdaEvent}; +use http::{HeaderMap, Method}; + +/// Main entry point for the AWS Lambda function. +#[tokio::main] +async fn main() -> Result<(), lambda_runtime::Error> { + // Run the lambda service. + lambda_runtime::run( + service_fn( + |event: LambdaEvent| handle_event(event) + ) + ).await +} + +/// Asynchronously handles incoming API Gateway events and dispatches them +/// to the correct method based on the route and method. +/// +/// # Arguments +/// * `event` - A LambdaEvent containing the ApiGatewayProxyRequest. +/// +/// # Returns +/// A result containing the API Gateway Proxy Response or an lambda_runtime::Error. +async fn handle_event( + event: LambdaEvent +) -> Result { + + // Extract base data. + let resource = event.payload.resource.unwrap_or_default(); + let http_method = event.payload.http_method; + let body = event.payload.body.clone(); + + // Dispatch based on API call. + match (resource.as_str(), http_method) { + ("/deposits", Method::POST) => { + + // Deserialize the create deposit request. + let request: CreateDepositRequestContent = body + .map(|serailzed_request| { + serde_json::from_str::(serailzed_request.as_str()) + .unwrap() // TODO: Handle lambda_runtime::Errors. https://github.com/stacks-network/sbtc/issues/111 + }) + .unwrap(); // TODO: Handle lambda_runtime::Errors. https://github.com/stacks-network/sbtc/issues/111 + + // Generate dummy response with all the necesary fields, taking + // the identifiers from the request. + let response = emily::models::CreateDepositResponseContent { + bitcoin_txid: request.bitcoin_txid.to_string(), + bitcoin_tx_output_index: request.bitcoin_tx_output_index, + recipient: "MOCK_RECIPIENT".to_string(), + amount: 11111.0, + status: emily::models::OpStatus::Pending, + status_message: "MOCK_CREATE_DEPOSIT_RESPONSE".to_string(), + parameters: Box::new(DepositParameters { + lock_time: Some(22222.0), + max_fee: Some(33333.0), + reclaim_script: Some("MOCK_RECLAIM_SCRIPT".to_string()) + }), + last_update_block_hash: None, // Unknown on creation. + last_update_height: None, // Unknown on creation. + fulfillment: None, // Unknown on creation. + }; + + // Serialize response. + let serialized_response: String = serde_json::to_string(&response) + .map_err(lambda_runtime::Error::from) + .unwrap(); + + // Setup CORS headers. + // TODO: Refactor ApiGatewayProxyResponse packaging into a helper function. + // https://github.com/stacks-network/sbtc/issues/111 + let mut headers = HeaderMap::new(); + headers.insert(header::CONTENT_TYPE, HeaderValue::from_static("application/json")); + headers.insert(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static("Content-Type")); + headers.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*")); + headers.insert(header::ACCESS_CONTROL_ALLOW_METHODS, HeaderValue::from_static("OPTIONS,POST,GET")); + Ok(ApiGatewayProxyResponse { + status_code: 201, + multi_value_headers: headers.clone(), + is_base64_encoded: false, + body: Some(Body::Text(serialized_response)), + headers, + }) + } + _ => { + // Generate Not implemented for all unmatched requests. + let response: emily::models::NotImplementedErrorResponseContent = emily::models::NotImplementedErrorResponseContent { + message: "API call not implemented.".to_string() + }; + + // Serialize response. + let serialized_response: String = serde_json::to_string(&response) + .map_err(lambda_runtime::Error::from) + .unwrap(); + + // Setup CORS headers. + // TODO: Refactor ApiGatewayProxyResponse packaging into a helper function. + // https://github.com/stacks-network/sbtc/issues/111 + let mut headers = HeaderMap::new(); + headers.insert(header::CONTENT_TYPE, HeaderValue::from_static("application/json")); + headers.insert(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static("Content-Type")); + headers.insert(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*")); + headers.insert(header::ACCESS_CONTROL_ALLOW_METHODS, HeaderValue::from_static("OPTIONS,POST,GET")); + Ok(ApiGatewayProxyResponse { + status_code: 501, + multi_value_headers: headers.clone(), + is_base64_encoded: false, + body: Some(Body::Text(serialized_response)), + headers, + }) + }, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use test_case::test_case; + + fn create_event(method: Method, resource: &str, body: Option) -> LambdaEvent { + LambdaEvent { + payload: ApiGatewayProxyRequest { + http_method: method, + resource: Some(resource.to_string()), + body, + ..Default::default() + }, + context: Default::default() + } + } + + #[tokio::test] + async fn test_post_deposits_successful() { + // Arrange. + let json_body = serde_json::to_string(&CreateDepositRequestContent { + bitcoin_txid: "BITCOIN_TXID_UNITTEST".to_string(), + bitcoin_tx_output_index: 0.0, + reclaim: "RECLAIM_UNITTEST".to_string(), + deposit: "DEPOSIT_UNITTEST".to_string(), + }).unwrap(); + let event = create_event(Method::POST, "/deposits", Some(json_body)); + + // Act. + let response = handle_event(event).await.expect("Failed to handle event"); + + // Assert. + assert_eq!(response.status_code, 201); + assert_eq!(response.body.unwrap(), Body::Text("{\"bitcoinTxid\":\"BITCOIN_TXID_UNITTEST\",\"bitcoinTxOutputIndex\":0.0,\"recipient\":\"MOCK_RECIPIENT\",\"amount\":11111.0,\"status\":\"PENDING\",\"statusMessage\":\"MOCK_CREATE_DEPOSIT_RESPONSE\",\"parameters\":{\"maxFee\":33333.0,\"lockTime\":22222.0,\"reclaimScript\":\"MOCK_RECLAIM_SCRIPT\"}}".to_string())); + } + + #[test_case(Method::GET, "/deposits/{txid}/{outputIndex}", None; "get-deposit")] + #[test_case(Method::GET, "/deposits/{txid}", None; "get-txn-deposits")] + #[test_case(Method::GET, "/deposits", None; "get-deposits")] + #[test_case(Method::PUT, "/deposits", None; "update-deposits")] + #[test_case(Method::POST, "/withdrawals", None; "create-withdrawal")] + #[test_case(Method::GET, "/withdrawals/{id}", None; "get-withdrawal")] + #[test_case(Method::GET, "/withdrawals", None; "get-withdrawals")] + #[test_case(Method::PUT, "/withdrawals", None; "update-withdrawals")] + #[test_case(Method::GET, "/chainstate/{height}", None; "get-chainstate")] + #[test_case(Method::PUT, "/chainstate/{height}", None; "set-chainstate")] + #[test_case(Method::POST, "/chainstate/{height}", None; "update-chainstate")] + #[tokio::test] + async fn test_method_not_implemented(method: Method, resource: &str, body: Option) { + // Arrange. + let event: LambdaEvent = create_event(method, resource, body); + + // Act. + let response: ApiGatewayProxyResponse = handle_event(event).await.expect("Failed to handle event"); + + // Assert. + assert_eq!(response.status_code, 501); + assert_eq!(response.body.unwrap(), Body::Text("{\"message\":\"API call not implemented.\"}".to_string())); + } +}