diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7dfe5d5a1..955a2d11c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,6 +4,16 @@ updates: directory: "/" schedule: interval: "daily" + ignore: + # Substrate and frontier related deps as all of them are controlled in our forks. + - dependency-name: "frame-*" + - dependency-name: "pallet-*" + - dependency-name: "sc-*" + - dependency-name: "sp-*" + - dependency-name: "fc-*" + - dependency-name: "fp-*" + - dependency-name: "substrate-*" + - dependency-name: "try-runtime-cli" - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.vscode/settings.json b/.vscode/settings.json index 5f0d34c1b..b758c2d4c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,13 +7,27 @@ "[toml]": { "editor.defaultFormatter": "tamasfe.even-better-toml" }, - // This takes too long when working with substrate, as it build the whole - // runtime each time the node host code is built. - "rust-analyzer.cargo.buildScripts.enable": false, - // Uncomment this while working on runtime. - // "rust-analyzer.cargo.target": "wasm32-unknown-unknown", - // "rust-analyzer.cargo.noDefaultFeatures": true, + // Avoid conflicts with command line. "rust-analyzer.cargo.targetDir": true, + // Improve stability. + "rust-analyzer.server.extraEnv": { + "CHALK_OVERFLOW_DEPTH": "100000000", + "CHALK_SOLVER_MAX_SIZE": "10000000" + }, + "rust-analyzer.cargo.features": "all", + "rust-analyzer.cargo.extraEnv": { + // Skip building WASM, there is never need for it here. + "SKIP_WASM_BUILD": "1" + }, + // Don't expand some problematic proc_macros + "rust-analyzer.procMacro.ignored": { + "async-trait": ["async_trait"], + "napi-derive": ["napi"], + "async-recursion": ["async_recursion"], + "async-std": ["async_std"] + }, + "rust-analyzer.workspace.symbol.search.scope": "workspace_and_dependencies", + "rust-analyzer.workspace.symbol.search.kind": "all_symbols", "vitest.commandLine": "yarn utils/e2e-tests/ts test:watch --", "vitest.include": [ "utils/e2e-tests/ts/**/tests/**/*.ts", diff --git a/Cargo.lock b/Cargo.lock index 2e753d2d1..5313c10e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "approx" @@ -580,13 +580,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -666,7 +666,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1253,9 +1253,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -1263,9 +1263,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -1282,7 +1282,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1744,7 +1744,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1771,7 +1771,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1788,7 +1788,7 @@ checksum = "35de3b547387863c8f82013c4f79f1c2162edee956383e4089e1d04c18c4f16c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -2088,7 +2088,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3450,7 +3450,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6121,7 +6121,7 @@ dependencies = [ "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6262,7 +6262,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -7110,7 +7110,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -7151,7 +7151,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -7393,7 +7393,7 @@ dependencies = [ "proc-macro2", "quote", "sha3 0.9.1", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -7754,9 +7754,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -7953,7 +7953,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -9748,29 +9748,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -9982,9 +9982,9 @@ dependencies = [ [[package]] name = "similar-asserts" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e041bb827d1bfca18f213411d51b665309f1afb37a04a5d1464530e13779fc0f" +checksum = "cfe85670573cd6f0fa97940f26e7e6601213c3b0555246c24234131f88c5709e" dependencies = [ "console", "similar", @@ -10990,7 +10990,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -11127,9 +11127,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -11232,7 +11232,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -11382,7 +11382,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -11569,7 +11569,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -11683,7 +11683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -12189,7 +12189,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -12223,7 +12223,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -13242,7 +13242,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -13262,7 +13262,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] diff --git a/crates/facetec-api-client/src/enrollment3d.rs b/crates/facetec-api-client/src/enrollment3d.rs index 825ffc4c9..86223032e 100644 --- a/crates/facetec-api-client/src/enrollment3d.rs +++ b/crates/facetec-api-client/src/enrollment3d.rs @@ -44,6 +44,8 @@ pub struct Response { /// The external database ID that was associated with this item. #[serde(rename = "externalDatabaseRefID")] pub external_database_ref_id: String, + /// Scan result blob. + pub scan_result_blob: String, /// Whether the request was successful. pub success: bool, } @@ -147,6 +149,7 @@ mod tests { }, "faceTecRetryScreen": 0, "retryScreenEnumInt": 0, + "scanResultBlob": "BLOOOB", "serverInfo": { "version": "9.0.5", "mode": "Development Only", @@ -160,12 +163,13 @@ mod tests { response, Response { external_database_ref_id, + scan_result_blob, success: true, face_scan: FaceScanResponse { age_estimate_group_enum_int: -1, .. }, - } if external_database_ref_id == "test_external_dbref_id" + } if external_database_ref_id == "test_external_dbref_id" && scan_result_blob == "BLOOOB" ) } @@ -181,7 +185,7 @@ mod tests { "ageEstimateGroupEnumInt": 2, "externalDatabaseRefID": "qwe", "retryScreenEnumInt": 0, - "scanResultBlob": "AQEAAABCAAAAAAAAABod8Ab2TBI4O9XmVyim3AxlDaV4QoP2eFBAmQTkB2dOiL4becto+NXWqUxdo6JBjSUoreo9Lm7MToQFpqj/HB+Hzw\\u003d\\u003d", + "scanResultBlob": "BLOOOB", "success": false, "wasProcessed": true, "callData": { @@ -206,6 +210,7 @@ mod tests { response, Response { external_database_ref_id, + scan_result_blob, success: false, face_scan: FaceScanResponse { face_scan_security_checks: FaceScanSecurityChecks { @@ -217,7 +222,7 @@ mod tests { retry_screen_enum_int: 0, age_estimate_group_enum_int: 2, }, - } if external_database_ref_id == "qwe" + } if external_database_ref_id == "qwe" && scan_result_blob == "BLOOOB" ) } @@ -261,6 +266,7 @@ mod tests { }, "faceTecRetryScreen": 0, "retryScreenEnumInt": 0, + "scanResultBlob": "BLOOOB", "serverInfo": { "version": "9.0.5", "mode": "Development Only", diff --git a/crates/robonode-client/src/authenticate.rs b/crates/robonode-client/src/authenticate.rs index 4dbe3c40e..da86dfcf5 100644 --- a/crates/robonode-client/src/authenticate.rs +++ b/crates/robonode-client/src/authenticate.rs @@ -96,7 +96,7 @@ mod tests { use wiremock::{matchers, Mock, MockServer, ResponseTemplate}; use super::*; - use crate::test_utils::mkerr; + use crate::test_utils::{mkerr, mkerr_containing_blob}; #[test] fn request_serialization() { @@ -131,6 +131,24 @@ mod tests { ) } + #[test] + fn response_deserialization_containing_blob() { + let sample_response = serde_json::json!({ + "authTicket": [1, 2, 3], + "authTicketSignature": [4, 5, 6], + "scanResultBlob": "blob".to_owned(), + }); + + let response: AuthenticateResponse = serde_json::from_value(sample_response).unwrap(); + assert_eq!( + response, + AuthenticateResponse { + auth_ticket: vec![1, 2, 3].into(), + auth_ticket_signature: vec![4, 5, 6].into(), + } + ) + } + #[tokio::test] async fn mock_success() { let mock_server = MockServer::start().await; @@ -163,6 +181,39 @@ mod tests { assert_eq!(actual_response, expected_response); } + #[tokio::test] + async fn mock_success_containing_blob() { + let mock_server = MockServer::start().await; + + let sample_request = AuthenticateRequest { + liveness_data: b"dummy liveness data", + liveness_data_signature: b"123", + }; + let sample_response = serde_json::json!({ + "authTicket": b"456", + "authTicketSignature": b"789", + "scanResultBlob": "blob".to_owned(), + }); + + let expected_response: AuthenticateResponse = + serde_json::from_value(sample_response.clone()).unwrap(); + + Mock::given(matchers::method("POST")) + .and(matchers::path("/authenticate")) + .and(matchers::body_json(&sample_request)) + .respond_with(ResponseTemplate::new(200).set_body_json(&sample_response)) + .mount(&mock_server) + .await; + + let client = Client { + base_url: mock_server.uri(), + reqwest: reqwest::Client::new(), + }; + + let actual_response = client.authenticate(sample_request).await.unwrap(); + assert_eq!(actual_response, expected_response); + } + #[tokio::test] async fn mock_error_response() { let cases = [ @@ -225,6 +276,69 @@ mod tests { } } + #[tokio::test] + async fn mock_error_response_containing_blob() { + let cases = [ + ( + StatusCode::BAD_REQUEST, + "AUTHENTICATE_INVALID_LIVENESS_DATA", + AuthenticateError::InvalidLivenessData, + ), + ( + StatusCode::NOT_FOUND, + "AUTHENTICATE_PERSON_NOT_FOUND", + AuthenticateError::PersonNotFound, + ), + ( + StatusCode::FORBIDDEN, + "AUTHENTICATE_FACE_SCAN_REJECTED", + AuthenticateError::FaceScanRejected, + ), + ( + StatusCode::FORBIDDEN, + "AUTHENTICATE_SIGNATURE_INVALID", + AuthenticateError::SignatureInvalid, + ), + ( + StatusCode::INTERNAL_SERVER_ERROR, + "LOGIC_INTERNAL_ERROR", + AuthenticateError::LogicInternal, + ), + ( + StatusCode::BAD_REQUEST, + "MY_ERR_CODE", + AuthenticateError::UnknownCode("MY_ERR_CODE".to_owned()), + ), + ]; + + for case in cases { + let mock_server = MockServer::start().await; + + let sample_request = AuthenticateRequest { + liveness_data: b"dummy liveness data", + liveness_data_signature: b"123", + }; + + let response = + ResponseTemplate::new(case.0).set_body_json(mkerr_containing_blob(case.1, "blob")); + + Mock::given(matchers::method("POST")) + .and(matchers::path("/authenticate")) + .and(matchers::body_json(&sample_request)) + .respond_with(response) + .mount(&mock_server) + .await; + + let client = Client { + base_url: mock_server.uri(), + reqwest: reqwest::Client::new(), + }; + + let actual_error = client.authenticate(sample_request).await.unwrap_err(); + assert_matches!(actual_error, Error::Call(err) if err == case.2); + } + } + #[tokio::test] async fn mock_error_unknown() { let mock_server = MockServer::start().await; diff --git a/crates/robonode-client/src/enroll.rs b/crates/robonode-client/src/enroll.rs index c71301580..55c96f5c9 100644 --- a/crates/robonode-client/src/enroll.rs +++ b/crates/robonode-client/src/enroll.rs @@ -89,7 +89,7 @@ mod tests { use wiremock::{matchers, Mock, MockServer, ResponseTemplate}; use super::*; - use crate::test_utils::mkerr; + use crate::test_utils::{mkerr, mkerr_containing_blob}; #[test] fn request_serialization() { @@ -134,6 +134,34 @@ mod tests { client.enroll(sample_request).await.unwrap(); } + #[tokio::test] + async fn mock_success_containing_blob() { + let mock_server = MockServer::start().await; + + let sample_request = EnrollRequest { + liveness_data: b"dummy liveness data", + public_key: b"123", + liveness_data_signature: b"signature", + }; + let sample_response = serde_json::json!({ + "scanResultBlob": "blob".to_owned(), + }); + + Mock::given(matchers::method("POST")) + .and(matchers::path("/enroll")) + .and(matchers::body_json(&sample_request)) + .respond_with(ResponseTemplate::new(201).set_body_json(&sample_response)) + .mount(&mock_server) + .await; + + let client = Client { + base_url: mock_server.uri(), + reqwest: reqwest::Client::new(), + }; + + client.enroll(sample_request).await.unwrap(); + } + #[tokio::test] async fn mock_error_response() { let cases = [ @@ -202,6 +230,75 @@ mod tests { } } + #[tokio::test] + async fn mock_error_response_containing_blob() { + let cases = [ + ( + StatusCode::BAD_REQUEST, + "ENROLL_INVALID_PUBLIC_KEY", + EnrollError::InvalidPublicKey, + ), + ( + StatusCode::BAD_REQUEST, + "ENROLL_INVALID_LIVENESS_DATA", + EnrollError::InvalidLivenessData, + ), + ( + StatusCode::FORBIDDEN, + "ENROLL_FACE_SCAN_REJECTED", + EnrollError::FaceScanRejected, + ), + ( + StatusCode::CONFLICT, + "ENROLL_PUBLIC_KEY_ALREADY_USED", + EnrollError::PublicKeyAlreadyUsed, + ), + ( + StatusCode::CONFLICT, + "ENROLL_PERSON_ALREADY_ENROLLED", + EnrollError::PersonAlreadyEnrolled, + ), + ( + StatusCode::INTERNAL_SERVER_ERROR, + "LOGIC_INTERNAL_ERROR", + EnrollError::LogicInternal, + ), + ( + StatusCode::BAD_REQUEST, + "MY_ERR_CODE", + EnrollError::UnknownCode("MY_ERR_CODE".to_owned()), + ), + ]; + + for case in cases { + let mock_server = MockServer::start().await; + + let sample_request = EnrollRequest { + liveness_data: b"dummy liveness data", + liveness_data_signature: b"signature", + public_key: b"123", + }; + + let response = + ResponseTemplate::new(case.0).set_body_json(mkerr_containing_blob(case.1, "blob")); + + Mock::given(matchers::method("POST")) + .and(matchers::path("/enroll")) + .and(matchers::body_json(&sample_request)) + .respond_with(response) + .mount(&mock_server) + .await; + + let client = Client { + base_url: mock_server.uri(), + reqwest: reqwest::Client::new(), + }; + + let actual_error = client.enroll(sample_request).await.unwrap_err(); + assert_matches!(actual_error, Error::Call(err) if err == case.2); + } + } + #[tokio::test] async fn mock_error_unknown() { let mock_server = MockServer::start().await; diff --git a/crates/robonode-client/src/error_response.rs b/crates/robonode-client/src/error_response.rs index d7c9faf16..3fbed2e01 100644 --- a/crates/robonode-client/src/error_response.rs +++ b/crates/robonode-client/src/error_response.rs @@ -21,7 +21,7 @@ impl TryFrom for ErrorResponse { #[cfg(test)] pub mod tests { use super::*; - use crate::test_utils::mkerr; + use crate::test_utils::{mkerr, mkerr_containing_blob}; #[test] fn decodes() { @@ -29,4 +29,11 @@ pub mod tests { let ErrorResponse { error_code } = err.try_into().unwrap(); assert_eq!(error_code, "MY_ERR_CODE"); } + + #[test] + fn decodes_containing_blob() { + let err = mkerr_containing_blob("MY_ERR_CODE", "scan result blob").to_string(); + let ErrorResponse { error_code } = err.try_into().unwrap(); + assert_eq!(error_code, "MY_ERR_CODE"); + } } diff --git a/crates/robonode-client/src/test_utils.rs b/crates/robonode-client/src/test_utils.rs index 79e708c23..624e34460 100644 --- a/crates/robonode-client/src/test_utils.rs +++ b/crates/robonode-client/src/test_utils.rs @@ -2,6 +2,10 @@ pub fn mkerr(error_code: &str) -> serde_json::Value { serde_json::json!({ "errorCode": error_code }) } +pub fn mkerr_containing_blob(error_code: &str, scan_result_blob: &str) -> serde_json::Value { + serde_json::json!({ "errorCode": error_code, "scanResultBlob": scan_result_blob }) +} + #[cfg(test)] mod tests { use super::*; @@ -12,5 +16,11 @@ mod tests { mkerr("MY_ERR_CODE").to_string(), serde_json::json!({ "errorCode": "MY_ERR_CODE" }).to_string() ); + + assert_eq!( + mkerr_containing_blob("MY_ERR_CODE", "scan result blob").to_string(), + serde_json::json!({ "errorCode": "MY_ERR_CODE", "scanResultBlob": "scan result blob" }) + .to_string() + ); } } diff --git a/crates/robonode-server/src/http/error.rs b/crates/robonode-server/src/http/error.rs index f56248f12..2a6eb1cf3 100644 --- a/crates/robonode-server/src/http/error.rs +++ b/crates/robonode-server/src/http/error.rs @@ -4,7 +4,7 @@ use warp::hyper::StatusCode; use crate::logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, - op_get_public_key, + op_get_public_key, ScanResultBlob, }; /// A logic error. @@ -14,51 +14,72 @@ pub struct Logic { pub status_code: StatusCode, /// A textual code representing the rejection message. pub error_code: &'static str, + /// Scan result blob. + pub scan_result_blob: Option, } impl warp::reject::Reject for Logic {} impl Logic { /// Create a new [`Logic`] error. - pub const fn new(status_code: StatusCode, error_code: &'static str) -> Self { + pub const fn new( + status_code: StatusCode, + error_code: &'static str, + scan_result_blob: Option, + ) -> Self { Self { status_code, error_code, + scan_result_blob, } } } -/// A kind of internal logic error occurred that we don't want to expose. -const INTERNAL: Logic = Logic::new(StatusCode::INTERNAL_SERVER_ERROR, "LOGIC_INTERNAL_ERROR"); +/// A helper function to return kind of internal logic error occurred that we don't want to expose. +fn internal_logic(scan_result_blob: Option) -> Logic { + Logic::new( + StatusCode::INTERNAL_SERVER_ERROR, + "LOGIC_INTERNAL_ERROR", + scan_result_blob, + ) +} impl From for Logic { fn from(err: op_enroll::Error) -> Self { match err { op_enroll::Error::InvalidPublicKey => { - Self::new(StatusCode::BAD_REQUEST, "ENROLL_INVALID_PUBLIC_KEY") - } - op_enroll::Error::InvalidLivenessData(_) => { - Self::new(StatusCode::BAD_REQUEST, "ENROLL_INVALID_LIVENESS_DATA") + Self::new(StatusCode::BAD_REQUEST, "ENROLL_INVALID_PUBLIC_KEY", None) } + op_enroll::Error::InvalidLivenessData(_) => Self::new( + StatusCode::BAD_REQUEST, + "ENROLL_INVALID_LIVENESS_DATA", + None, + ), op_enroll::Error::SignatureInvalid => { - Self::new(StatusCode::BAD_REQUEST, "ENROLL_SIGNATURE_INVALID") - } - op_enroll::Error::FaceScanRejected => { - Self::new(StatusCode::FORBIDDEN, "ENROLL_FACE_SCAN_REJECTED") + Self::new(StatusCode::BAD_REQUEST, "ENROLL_SIGNATURE_INVALID", None) } + op_enroll::Error::FaceScanRejected(scan_result_blob) => Self::new( + StatusCode::FORBIDDEN, + "ENROLL_FACE_SCAN_REJECTED", + Some(scan_result_blob), + ), op_enroll::Error::PublicKeyAlreadyUsed => { - Self::new(StatusCode::CONFLICT, "ENROLL_PUBLIC_KEY_ALREADY_USED") + Self::new(StatusCode::CONFLICT, "ENROLL_PUBLIC_KEY_ALREADY_USED", None) } - op_enroll::Error::PersonAlreadyEnrolled => { - Self::new(StatusCode::CONFLICT, "ENROLL_PERSON_ALREADY_ENROLLED") + op_enroll::Error::PersonAlreadyEnrolled(scan_result_blob) => Self::new( + StatusCode::CONFLICT, + "ENROLL_PERSON_ALREADY_ENROLLED", + Some(scan_result_blob), + ), + op_enroll::Error::InternalErrorEnrollmentUnsuccessful(scan_result_blob) + | op_enroll::Error::InternalErrorDbSearch(_, scan_result_blob) + | op_enroll::Error::InternalErrorDbSearchUnsuccessful(scan_result_blob) + | op_enroll::Error::InternalErrorDbEnroll(_, scan_result_blob) + | op_enroll::Error::InternalErrorDbEnrollUnsuccessful(scan_result_blob) => { + internal_logic(Some(scan_result_blob)) } op_enroll::Error::InternalErrorEnrollment(_) - | op_enroll::Error::InternalErrorEnrollmentUnsuccessful - | op_enroll::Error::InternalErrorDbSearch(_) - | op_enroll::Error::InternalErrorDbSearchUnsuccessful - | op_enroll::Error::InternalErrorDbEnroll(_) - | op_enroll::Error::InternalErrorSignatureVerificationFailed - | op_enroll::Error::InternalErrorDbEnrollUnsuccessful => INTERNAL.clone(), + | op_enroll::Error::InternalErrorSignatureVerificationFailed => internal_logic(None), } } } @@ -69,25 +90,34 @@ impl From for Logic { op_authenticate::Error::InvalidLivenessData(_) => Self::new( StatusCode::BAD_REQUEST, "AUTHENTICATE_INVALID_LIVENESS_DATA", + None, ), - op_authenticate::Error::PersonNotFound => { - Self::new(StatusCode::NOT_FOUND, "AUTHENTICATE_PERSON_NOT_FOUND") - } - op_authenticate::Error::FaceScanRejected => { - Self::new(StatusCode::FORBIDDEN, "AUTHENTICATE_FACE_SCAN_REJECTED") - } - op_authenticate::Error::SignatureInvalid => { - Self::new(StatusCode::FORBIDDEN, "AUTHENTICATE_SIGNATURE_INVALID") + op_authenticate::Error::PersonNotFound(scan_result_blob) => Self::new( + StatusCode::NOT_FOUND, + "AUTHENTICATE_PERSON_NOT_FOUND", + Some(scan_result_blob), + ), + op_authenticate::Error::FaceScanRejected(scan_result_blob) => Self::new( + StatusCode::FORBIDDEN, + "AUTHENTICATE_FACE_SCAN_REJECTED", + Some(scan_result_blob), + ), + op_authenticate::Error::SignatureInvalid(scan_result_blob) => Self::new( + StatusCode::FORBIDDEN, + "AUTHENTICATE_SIGNATURE_INVALID", + Some(scan_result_blob), + ), + op_authenticate::Error::InternalErrorEnrollmentUnsuccessful(scan_result_blob) + | op_authenticate::Error::InternalErrorDbSearch(_, scan_result_blob) + | op_authenticate::Error::InternalErrorDbSearchUnsuccessful(scan_result_blob) + | op_authenticate::Error::InternalErrorDbSearchMatchLevelMismatch(scan_result_blob) + | op_authenticate::Error::InternalErrorInvalidPublicKeyHex(scan_result_blob) + | op_authenticate::Error::InternalErrorInvalidPublicKey(scan_result_blob) + | op_authenticate::Error::InternalErrorSignatureVerificationFailed(scan_result_blob) + | op_authenticate::Error::InternalErrorAuthTicketSigningFailed(scan_result_blob) => { + internal_logic(Some(scan_result_blob)) } - op_authenticate::Error::InternalErrorEnrollment(_) - | op_authenticate::Error::InternalErrorEnrollmentUnsuccessful - | op_authenticate::Error::InternalErrorDbSearch(_) - | op_authenticate::Error::InternalErrorDbSearchUnsuccessful - | op_authenticate::Error::InternalErrorDbSearchMatchLevelMismatch - | op_authenticate::Error::InternalErrorInvalidPublicKeyHex - | op_authenticate::Error::InternalErrorInvalidPublicKey - | op_authenticate::Error::InternalErrorSignatureVerificationFailed - | op_authenticate::Error::InternalErrorAuthTicketSigningFailed => INTERNAL.clone(), + op_authenticate::Error::InternalErrorEnrollment(_) => internal_logic(None), } } } @@ -103,7 +133,7 @@ impl From for Logic { match err { op_get_facetec_session_token::Error::InternalErrorSessionToken(_) | op_get_facetec_session_token::Error::InternalErrorSessionTokenUnsuccessful => { - INTERNAL.clone() + internal_logic(None) } } } diff --git a/crates/robonode-server/src/http/filters.rs b/crates/robonode-server/src/http/filters.rs index 96b32431d..3ecdbd55a 100644 --- a/crates/robonode-server/src/http/filters.rs +++ b/crates/robonode-server/src/http/filters.rs @@ -49,6 +49,7 @@ where + Send + Sync, >::Error: Into, + >::Response: Serialize, >::Error: Into, >::Response: Serialize, >::Error: Into, @@ -72,6 +73,7 @@ fn enroll( where L: LogicOp + Send + Sync, L::Error: Into, + L::Response: Serialize, { warp::path!("enroll") .and(warp::post()) diff --git a/crates/robonode-server/src/http/handlers.rs b/crates/robonode-server/src/http/handlers.rs index 5a7f2ee16..090afb8ce 100644 --- a/crates/robonode-server/src/http/handlers.rs +++ b/crates/robonode-server/src/http/handlers.rs @@ -20,9 +20,13 @@ pub async fn enroll( where L: LogicOp, L::Error: Into, + L::Response: Serialize, { - logic.call(input).await.map_err(Into::into)?; - Ok(StatusCode::CREATED) + let res = logic.call(input).await.map_err(Into::into)?; + + let reply = warp::reply::json(&res); + let reply = warp::reply::with_status(reply, StatusCode::CREATED); + Ok(reply.into_response()) } /// Authenticate operation HTTP transport coupling. diff --git a/crates/robonode-server/src/http/rejection.rs b/crates/robonode-server/src/http/rejection.rs index e08c06cca..d3c4850ef 100644 --- a/crates/robonode-server/src/http/rejection.rs +++ b/crates/robonode-server/src/http/rejection.rs @@ -4,6 +4,7 @@ use serde::Serialize; use warp::{hyper::StatusCode, Reply}; use super::error; +use crate::logic::ScanResultBlob; /// Error response shape that we can return for the error body. #[derive(Debug, Serialize)] @@ -11,17 +12,28 @@ use super::error; pub(super) struct ErrorResponse { /// The machine-readable error code describing the error condition. pub error_code: &'static str, + /// Scan result blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub scan_result_blob: Option, } /// This function receives a `Rejection` and generates an error response. pub async fn handle(err: warp::reject::Rejection) -> Result { - let (status_code, error_code) = if let Some(logic_error) = err.find::() { - (logic_error.status_code, logic_error.error_code) - } else { - (StatusCode::NOT_IMPLEMENTED, "UNKNOWN_CALL") - }; - - let json = warp::reply::json(&ErrorResponse { error_code }); + let (status_code, error_code, scan_result_blob) = + if let Some(logic_error) = err.find::() { + ( + logic_error.status_code, + logic_error.error_code, + logic_error.scan_result_blob.clone(), + ) + } else { + (StatusCode::NOT_IMPLEMENTED, "UNKNOWN_CALL", None) + }; + + let json = warp::reply::json(&ErrorResponse { + error_code, + scan_result_blob, + }); Ok(warp::reply::with_status(json, status_code)) } @@ -33,9 +45,13 @@ mod tests { fn serializes_properly() { let body = serde_json::to_string(&ErrorResponse { error_code: "MY_ERR_CODE", + scan_result_blob: Some("scan result blob".to_owned()), }) .unwrap(); - assert_eq!(body, r#"{"errorCode":"MY_ERR_CODE"}"#); + assert_eq!( + body, + r#"{"errorCode":"MY_ERR_CODE","scanResultBlob":"scan result blob"}"# + ); } } diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 2ced55575..c2812ed8f 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -14,7 +14,7 @@ use crate::{ http::{rejection, root}, logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, - op_get_public_key, LogicOp, + op_get_public_key, LogicOp, ScanResultBlob, }, }; @@ -45,7 +45,6 @@ macro_rules! impl_Logic { macro_rules! assert_success_response { ($response:expr, $expected_response:expr) => { match $expected_response { - SuccessResponse::Empty => assert!($response.is_empty()), SuccessResponse::Json(body) => { assert_eq!( body, @@ -108,6 +107,7 @@ macro_rules! trivial_error_tests { injected_error = $mock_error:expr, expected_status = $status_code:expr, expected_code = $error_code:expr, + expected_scan_result_blob = $scan_result_blob:expr, }, )* ) => { @@ -127,7 +127,11 @@ macro_rules! trivial_error_tests { .reply(&filter) .await; - let expected_error_body_response = expect_error_body_response($status_code, $error_code).await; + let expected_error_body_response = expect_error_body_response( + $status_code, + $error_code, + $scan_result_blob, + ).await; assert_eq!(res.status(), $status_code); assert_eq!(res.body(), &expected_error_body_response); @@ -179,8 +183,12 @@ impl_Logic!( async fn expect_error_body_response( status_code: StatusCode, error_code: &'static str, + scan_result_blob: Option, ) -> warp::hyper::body::Bytes { - let json = warp::reply::json(&rejection::ErrorResponse { error_code }); + let json = warp::reply::json(&rejection::ErrorResponse { + error_code, + scan_result_blob, + }); let response = warp::reply::with_status(json, status_code).into_response(); warp::hyper::body::to_bytes(response).await.unwrap() } @@ -194,7 +202,6 @@ fn root_with_error_handler( /// Possible response variants we can expect in trivial success tests. #[derive(Debug)] enum SuccessResponse { - Empty, Json(serde_json::Value), } @@ -210,9 +217,11 @@ trivial_success_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_enroll, - injected_response = op_enroll::Response, + injected_response = op_enroll::Response {scan_result_blob: "scan result blob".to_owned()}, expected_status = StatusCode::CREATED, - expected_response = SuccessResponse::Empty, + expected_response = SuccessResponse::Json(serde_json::json!({ + "scanResultBlob": "scan result blob", + })), }, /// This test verifies getting expected HTTP response during successful authentication request. @@ -228,11 +237,13 @@ trivial_success_tests! [ injected_response = op_authenticate::Response { auth_ticket: OpaqueAuthTicket(b"ticket".to_vec()), auth_ticket_signature: b"signature".to_vec(), + scan_result_blob: "scan result blob".to_owned(), }, expected_status = StatusCode::OK, expected_response = SuccessResponse::Json(serde_json::json!({ "authTicket": b"ticket".to_vec(), "authTicketSignature": b"signature".to_vec(), + "scanResultBlob": "scan result blob", })), }, @@ -328,6 +339,7 @@ trivial_error_tests! [ injected_error = op_enroll::Error::InvalidPublicKey, expected_status = StatusCode::BAD_REQUEST, expected_code = "ENROLL_INVALID_PUBLIC_KEY", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -345,6 +357,7 @@ trivial_error_tests! [ injected_error = op_enroll::Error::SignatureInvalid, expected_status = StatusCode::BAD_REQUEST, expected_code = "ENROLL_SIGNATURE_INVALID", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -362,6 +375,7 @@ trivial_error_tests! [ injected_error = op_enroll::Error::InvalidLivenessData(codec::Error::from("invalid_data")), expected_status = StatusCode::BAD_REQUEST, expected_code = "ENROLL_INVALID_LIVENESS_DATA", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -376,9 +390,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_enroll, - injected_error = op_enroll::Error::FaceScanRejected, + injected_error = op_enroll::Error::FaceScanRejected("scan result blob".to_owned()), expected_status = StatusCode::FORBIDDEN, expected_code = "ENROLL_FACE_SCAN_REJECTED", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -396,6 +411,7 @@ trivial_error_tests! [ injected_error = op_enroll::Error::PublicKeyAlreadyUsed, expected_status = StatusCode::CONFLICT, expected_code = "ENROLL_PUBLIC_KEY_ALREADY_USED", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -410,9 +426,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_enroll, - injected_error = op_enroll::Error::PersonAlreadyEnrolled, + injected_error = op_enroll::Error::PersonAlreadyEnrolled("scan result blob".to_owned()), expected_status = StatusCode::CONFLICT, expected_code = "ENROLL_PERSON_ALREADY_ENROLLED", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -432,6 +449,7 @@ trivial_error_tests! [ })), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -446,9 +464,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_enroll, - injected_error = op_enroll::Error::InternalErrorEnrollmentUnsuccessful, + injected_error = op_enroll::Error::InternalErrorEnrollmentUnsuccessful("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -465,9 +484,10 @@ trivial_error_tests! [ mocked_call = expect_enroll, injected_error = op_enroll::Error::InternalErrorDbSearch(facetec_api_client::Error::Server(ServerError { error_message: "error".to_owned() - })), + }), "scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -482,9 +502,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_enroll, - injected_error = op_enroll::Error::InternalErrorDbSearchUnsuccessful, + injected_error = op_enroll::Error::InternalErrorDbSearchUnsuccessful("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -501,9 +522,10 @@ trivial_error_tests! [ mocked_call = expect_enroll, injected_error = op_enroll::Error::InternalErrorDbEnroll(facetec_api_client::Error::Server(ServerError { error_message: "error".to_owned() - })), + }), "scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -518,9 +540,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_enroll, - injected_error = op_enroll::Error::InternalErrorDbEnrollUnsuccessful, + injected_error = op_enroll::Error::InternalErrorDbEnrollUnsuccessful("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -537,6 +560,7 @@ trivial_error_tests! [ injected_error = op_authenticate::Error::InvalidLivenessData(codec::Error::from("invalid_data")), expected_status = StatusCode::BAD_REQUEST, expected_code = "AUTHENTICATE_INVALID_LIVENESS_DATA", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -550,9 +574,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::FaceScanRejected, + injected_error = op_authenticate::Error::FaceScanRejected("scan result blob".to_owned()), expected_status = StatusCode::FORBIDDEN, expected_code = "AUTHENTICATE_FACE_SCAN_REJECTED", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -566,9 +591,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::PersonNotFound, + injected_error = op_authenticate::Error::PersonNotFound("scan result blob".to_owned()), expected_status = StatusCode::NOT_FOUND, expected_code = "AUTHENTICATE_PERSON_NOT_FOUND", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -582,9 +608,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::SignatureInvalid, + injected_error = op_authenticate::Error::SignatureInvalid("scan result blob".to_owned()), expected_status = StatusCode::FORBIDDEN, expected_code = "AUTHENTICATE_SIGNATURE_INVALID", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -605,6 +632,7 @@ trivial_error_tests! [ )), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = None, }, /// This test verifies getting expected HTTP response @@ -618,9 +646,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorEnrollmentUnsuccessful, + injected_error = op_authenticate::Error::InternalErrorEnrollmentUnsuccessful("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -638,9 +667,10 @@ trivial_error_tests! [ ServerError { error_message: "error".to_owned() } - )), + ), "scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -654,9 +684,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorDbSearchUnsuccessful, + injected_error = op_authenticate::Error::InternalErrorDbSearchUnsuccessful("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -670,9 +701,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorDbSearchMatchLevelMismatch, + injected_error = op_authenticate::Error::InternalErrorDbSearchMatchLevelMismatch("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -686,9 +718,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorInvalidPublicKeyHex, + injected_error = op_authenticate::Error::InternalErrorInvalidPublicKeyHex("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -702,9 +735,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorInvalidPublicKey, + injected_error = op_authenticate::Error::InternalErrorInvalidPublicKey("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -718,9 +752,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorSignatureVerificationFailed, + injected_error = op_authenticate::Error::InternalErrorSignatureVerificationFailed("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response @@ -734,9 +769,10 @@ trivial_error_tests! [ liveness_data_signature: b"signature".to_vec(), }, mocked_call = expect_authenticate, - injected_error = op_authenticate::Error::InternalErrorAuthTicketSigningFailed, + injected_error = op_authenticate::Error::InternalErrorAuthTicketSigningFailed("scan result blob".to_owned()), expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = Some("scan result blob".to_owned()), }, /// This test verifies getting expected HTTP response during @@ -750,5 +786,6 @@ trivial_error_tests! [ injected_error = op_get_facetec_session_token::Error::InternalErrorSessionTokenUnsuccessful, expected_status = StatusCode::INTERNAL_SERVER_ERROR, expected_code = "LOGIC_INTERNAL_ERROR", + expected_scan_result_blob = None, }, ]; diff --git a/crates/robonode-server/src/logic/mod.rs b/crates/robonode-server/src/logic/mod.rs index f383afe02..695f8ed38 100644 --- a/crates/robonode-server/src/logic/mod.rs +++ b/crates/robonode-server/src/logic/mod.rs @@ -20,6 +20,9 @@ pub mod traits; pub use traits::*; +/// A type alias representing a scan result blob. +pub(crate) type ScanResultBlob = String; + /// The overall generic logic. pub struct Logic { /// The mutex over the locked portions of the logic. diff --git a/crates/robonode-server/src/logic/op_authenticate.rs b/crates/robonode-server/src/logic/op_authenticate.rs index 8625b98d4..73cdd6c99 100644 --- a/crates/robonode-server/src/logic/op_authenticate.rs +++ b/crates/robonode-server/src/logic/op_authenticate.rs @@ -6,7 +6,7 @@ use primitives_liveness_data::{LivenessData, OpaqueLivenessData}; use serde::{Deserialize, Serialize}; use tracing::{error, trace}; -use super::{common::*, Logic, LogicOp, Signer, Verifier}; +use super::{common::*, Logic, LogicOp, ScanResultBlob, Signer, Verifier}; use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; /// The request of the authenticate operation. @@ -33,6 +33,8 @@ pub struct Response { /// auth ticket was vetted by the robonode and verified to be associated /// with a FaceScan. pub auth_ticket_signature: Vec, + /// Scan result blob. + pub scan_result_blob: ScanResultBlob, } /// Errors for the authenticate operation. @@ -44,38 +46,38 @@ pub enum Error { /// The provided opaque liveness data could not be decoded. InvalidLivenessData(>::Error), /// This FaceScan was rejected. - FaceScanRejected, + FaceScanRejected(ScanResultBlob), /// This person was not found. /// Unually this means they need to enroll, but it can also happen if /// matching returns false-negative. - PersonNotFound, + PersonNotFound(ScanResultBlob), /// The liveness data signature validation failed. /// This means that the user might've provided a signature using different /// keypair from what was used for the original enrollment. - SignatureInvalid, + SignatureInvalid(ScanResultBlob), /// Internal error at server-level enrollment due to the underlying request /// error at the API level. InternalErrorEnrollment(ft::Error), /// Internal error at server-level enrollment due to unsuccessful response, /// but for some other reason but the FaceScan being rejected. /// Rejected FaceScan is explicitly encoded via a different error condition. - InternalErrorEnrollmentUnsuccessful, + InternalErrorEnrollmentUnsuccessful(ScanResultBlob), /// Internal error at 3D-DB search due to the underlying request /// error at the API level. - InternalErrorDbSearch(ft::Error), + InternalErrorDbSearch(ft::Error, ScanResultBlob), /// Internal error at 3D-DB search due to unsuccessful response. - InternalErrorDbSearchUnsuccessful, + InternalErrorDbSearchUnsuccessful(ScanResultBlob), /// Internal error at 3D-DB search due to match-level mismatch in /// the search results. - InternalErrorDbSearchMatchLevelMismatch, + InternalErrorDbSearchMatchLevelMismatch(ScanResultBlob), /// Internal error at converting public key hex representation to bytes. - InternalErrorInvalidPublicKeyHex, + InternalErrorInvalidPublicKeyHex(ScanResultBlob), /// Internal error at public key loading due to invalid public key. - InternalErrorInvalidPublicKey, + InternalErrorInvalidPublicKey(ScanResultBlob), /// Internal error at signature verification. - InternalErrorSignatureVerificationFailed, + InternalErrorSignatureVerificationFailed(ScanResultBlob), /// Internal error when signing auth ticket. - InternalErrorAuthTicketSigningFailed, + InternalErrorAuthTicketSigningFailed(ScanResultBlob), } #[async_trait::async_trait] @@ -125,13 +127,17 @@ where .face_scan_security_checks .all_checks_succeeded() { - return Err(Error::FaceScanRejected); + return Err(Error::FaceScanRejected(enroll_res.scan_result_blob)); } - return Err(Error::InternalErrorEnrollmentUnsuccessful); + return Err(Error::InternalErrorEnrollmentUnsuccessful( + enroll_res.scan_result_blob, + )); } - drop(enroll_res); + let ft::enrollment3d::Response { + scan_result_blob, .. + } = enroll_res; let search_result = unlocked .facetec @@ -143,7 +149,9 @@ where .await; let results = match db_search_result_adapter(search_result) { - DbSearchResult::OtherError(err) => return Err(Error::InternalErrorDbSearch(err)), + DbSearchResult::OtherError(err) => { + return Err(Error::InternalErrorDbSearch(err, scan_result_blob)) + } DbSearchResult::NoGroupError => { trace!(message = "Got no-group error instead of FaceTec 3D-DB search results, assuming no results"); vec![] @@ -151,7 +159,7 @@ where DbSearchResult::Response(search_res) => { trace!(message = "Got FaceTec 3D-DB search results", ?search_res); if !search_res.success { - return Err(Error::InternalErrorDbSearchUnsuccessful); + return Err(Error::InternalErrorDbSearchUnsuccessful(scan_result_blob)); } search_res.results } @@ -159,23 +167,40 @@ where // If the results set is empty - this means that this person was not // found in the system. - let found = results.first().ok_or(Error::PersonNotFound)?; + let Some(found) = results.first() else { + return Err(Error::PersonNotFound(scan_result_blob)); + }; + if found.match_level < MATCH_LEVEL { - return Err(Error::InternalErrorDbSearchMatchLevelMismatch); + return Err(Error::InternalErrorDbSearchMatchLevelMismatch( + scan_result_blob, + )); } - let public_key_bytes = - hex::decode(&found.identifier).map_err(|_| Error::InternalErrorInvalidPublicKeyHex)?; - let public_key = - PK::try_from(&public_key_bytes).map_err(|_| Error::InternalErrorInvalidPublicKey)?; + let public_key_bytes = match hex::decode(&found.identifier) { + Ok(public_key_bytes) => public_key_bytes, + Err(_) => return Err(Error::InternalErrorInvalidPublicKeyHex(scan_result_blob)), + }; + + let public_key = match PK::try_from(&public_key_bytes) { + Ok(public_key) => public_key, + Err(_) => return Err(Error::InternalErrorInvalidPublicKey(scan_result_blob)), + }; - let signature_valid = public_key + let signature_valid = match public_key .verify(&req.liveness_data, req.liveness_data_signature) .await - .map_err(|_| Error::InternalErrorSignatureVerificationFailed)?; + { + Ok(signature_valid) => signature_valid, + Err(_) => { + return Err(Error::InternalErrorSignatureVerificationFailed( + scan_result_blob, + )) + } + }; if !signature_valid { - return Err(Error::SignatureInvalid); + return Err(Error::SignatureInvalid(scan_result_blob)); } // Prepare an authentication nonce from the sequence number. @@ -193,15 +218,19 @@ where // Sign the auth ticket with our private key, so that later on it's possible to validate // this ticket was issues by us. - let auth_ticket_signature = unlocked - .signer - .sign(&opaque_auth_ticket) - .await - .map_err(|_| Error::InternalErrorAuthTicketSigningFailed)?; + let auth_ticket_signature = match unlocked.signer.sign(&opaque_auth_ticket).await { + Ok(auth_ticket_signature) => auth_ticket_signature, + Err(_) => { + return Err(Error::InternalErrorAuthTicketSigningFailed( + scan_result_blob, + )) + } + }; Ok(Response { auth_ticket: opaque_auth_ticket, auth_ticket_signature, + scan_result_blob, }) } } diff --git a/crates/robonode-server/src/logic/op_enroll.rs b/crates/robonode-server/src/logic/op_enroll.rs index bc4195027..ebf8480e9 100644 --- a/crates/robonode-server/src/logic/op_enroll.rs +++ b/crates/robonode-server/src/logic/op_enroll.rs @@ -5,7 +5,7 @@ use primitives_liveness_data::{LivenessData, OpaqueLivenessData}; use serde::{Deserialize, Serialize}; use tracing::{error, trace}; -use super::{common::*, Logic, LogicOp, Signer, Verifier}; +use super::{common::*, Logic, LogicOp, ScanResultBlob, Signer, Verifier}; use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; /// The request for the enroll operation. @@ -24,7 +24,10 @@ pub struct Request { /// The response for the enroll operation. #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] -pub struct Response; +pub struct Response { + /// Scan result blob. + pub scan_result_blob: ScanResultBlob, +} /// The errors on the enroll operation. /// @@ -39,29 +42,29 @@ pub enum Error { /// The liveness data signature validation failed. SignatureInvalid, /// This FaceScan was rejected. - FaceScanRejected, + FaceScanRejected(ScanResultBlob), /// This Public Key was already used. PublicKeyAlreadyUsed, /// This person has already enrolled into the system. /// It can also happen if matching returns false-positive. - PersonAlreadyEnrolled, + PersonAlreadyEnrolled(ScanResultBlob), /// Internal error at server-level enrollment due to the underlying request /// error at the API level. InternalErrorEnrollment(ft::Error), /// Internal error at server-level enrollment due to unsuccessful response, /// but for some other reason but the FaceScan being rejected. /// Rejected FaceScan is explicitly encoded via a different error condition. - InternalErrorEnrollmentUnsuccessful, + InternalErrorEnrollmentUnsuccessful(ScanResultBlob), /// Internal error at 3D-DB search due to the underlying request /// error at the API level. - InternalErrorDbSearch(ft::Error), + InternalErrorDbSearch(ft::Error, ScanResultBlob), /// Internal error at 3D-DB search due to unsuccessful response. - InternalErrorDbSearchUnsuccessful, + InternalErrorDbSearchUnsuccessful(ScanResultBlob), /// Internal error at 3D-DB enrollment due to the underlying request /// error at the API level. - InternalErrorDbEnroll(ft::Error), + InternalErrorDbEnroll(ft::Error, ScanResultBlob), /// Internal error at 3D-DB enrollment due to unsuccessful response. - InternalErrorDbEnrollUnsuccessful, + InternalErrorDbEnrollUnsuccessful(ScanResultBlob), /// Internal error at signature verification. InternalErrorSignatureVerificationFailed, } @@ -72,7 +75,7 @@ where S: Signer> + Send + 'static, PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]> + Verifier>, { - type Response = (); + type Response = Response; type Error = Error; /// An enroll invocation handler. @@ -125,12 +128,16 @@ where .face_scan_security_checks .all_checks_succeeded() { - return Err(Error::FaceScanRejected); + return Err(Error::FaceScanRejected(enroll_res.scan_result_blob)); } - return Err(Error::InternalErrorEnrollmentUnsuccessful); + return Err(Error::InternalErrorEnrollmentUnsuccessful( + enroll_res.scan_result_blob, + )); } - drop(enroll_res); + let ft::enrollment3d::Response { + scan_result_blob, .. + } = enroll_res; let search_result = unlocked .facetec @@ -142,7 +149,9 @@ where .await; let results = match db_search_result_adapter(search_result) { - DbSearchResult::OtherError(err) => return Err(Error::InternalErrorDbSearch(err)), + DbSearchResult::OtherError(err) => { + return Err(Error::InternalErrorDbSearch(err, scan_result_blob)) + } DbSearchResult::NoGroupError => { trace!(message = "Got no-group error instead of FaceTec 3D-DB search results, assuming no results"); vec![] @@ -150,7 +159,7 @@ where DbSearchResult::Response(search_res) => { trace!(message = "Got FaceTec 3D-DB search results", ?search_res); if !search_res.success { - return Err(Error::InternalErrorDbSearchUnsuccessful); + return Err(Error::InternalErrorDbSearchUnsuccessful(scan_result_blob)); } search_res.results } @@ -159,24 +168,27 @@ where // If the results set is non-empty - this means that this person has // already enrolled with the system. It might also be a false-positive. if !results.is_empty() { - return Err(Error::PersonAlreadyEnrolled); + return Err(Error::PersonAlreadyEnrolled(scan_result_blob)); } - let db_enroll_res = unlocked + let db_enroll_res = match unlocked .facetec .db_enroll(ft::db_enroll::Request { external_database_ref_id: &public_key_hex, group_name: DB_GROUP_NAME, }) .await - .map_err(Error::InternalErrorDbEnroll)?; + { + Ok(db_enroll_res) => db_enroll_res, + Err(err) => return Err(Error::InternalErrorDbEnroll(err, scan_result_blob)), + }; trace!(message = "Got FaceTec 3D-DB enroll results", ?db_enroll_res); if !db_enroll_res.success { - return Err(Error::InternalErrorDbEnrollUnsuccessful); + return Err(Error::InternalErrorDbEnrollUnsuccessful(scan_result_blob)); } - Ok(()) + Ok(Response { scan_result_blob }) } } diff --git a/utils/checks/snapshots/features.yaml b/utils/checks/snapshots/features.yaml index 090b6ca6c..9994249a0 100644 --- a/utils/checks/snapshots/features.yaml +++ b/utils/checks/snapshots/features.yaml @@ -86,7 +86,7 @@ features: [] - name: anstyle-wincon 3.0.4 features: [] -- name: anyhow 1.0.86 +- name: anyhow 1.0.87 features: - default - std @@ -167,7 +167,7 @@ features: - default - std -- name: async-trait 0.1.81 +- name: async-trait 0.1.82 features: [] - name: asynchronous-codec 0.6.2 features: @@ -410,7 +410,7 @@ - clang_6_0 - libloading - runtime -- name: clap 4.5.16 +- name: clap 4.5.17 features: - color - default @@ -422,7 +422,7 @@ - string - suggestions - usage -- name: clap_builder 4.5.15 +- name: clap_builder 4.5.17 features: - color - deprecated @@ -2506,7 +2506,7 @@ - rustls - tls-rustls - webpki -- name: quote 1.0.36 +- name: quote 1.0.37 features: - default - proc-macro @@ -3010,7 +3010,7 @@ - std - name: semver-parser 0.7.0 features: [] -- name: serde 1.0.208 +- name: serde 1.0.210 features: - alloc - default @@ -3018,10 +3018,10 @@ - rc - serde_derive - std -- name: serde_derive 1.0.208 +- name: serde_derive 1.0.210 features: - default -- name: serde_json 1.0.125 +- name: serde_json 1.0.128 features: - alloc - default @@ -3104,7 +3104,7 @@ - text - unicode - unicode-segmentation -- name: similar-asserts 1.5.0 +- name: similar-asserts 1.6.0 features: - default - unicode @@ -3520,7 +3520,7 @@ - quote - visit - visit-mut -- name: syn 2.0.75 +- name: syn 2.0.77 features: - clone-impls - default diff --git a/utils/e2e-tests/bash/package.json b/utils/e2e-tests/bash/package.json index 0bfa68bf9..6051a7de1 100644 --- a/utils/e2e-tests/bash/package.json +++ b/utils/e2e-tests/bash/package.json @@ -4,6 +4,6 @@ "private": true, "type": "module", "dependencies": { - "@polkadot/api-cli": "^0.57.3" + "@polkadot/api-cli": "^0.57.4" } } diff --git a/utils/e2e-tests/ts/package.json b/utils/e2e-tests/ts/package.json index a6f0d0db5..622a760e6 100644 --- a/utils/e2e-tests/ts/package.json +++ b/utils/e2e-tests/ts/package.json @@ -8,13 +8,13 @@ "test:ui": "vitest --ui" }, "dependencies": { - "@polkadot/api": "^12.3.1", - "@types/node": "22.4.1", + "@polkadot/api": "^12.4.2", + "@types/node": "22.5.4", "@vitest/expect": "^2.0.5", - "axios": "^1.7.4", + "axios": "^1.7.7", "ethers": "^6.13.2", "typescript": "^5.5.4", - "viem": "^2.19.7", + "viem": "^2.21.3", "vitest": "^2.0.5" } } diff --git a/yarn.lock b/yarn.lock index a9497f88b..846e8cdae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -303,6 +303,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:~1.5.0": + version: 1.5.0 + resolution: "@noble/hashes@npm:1.5.0" + checksum: 9cc031d5c888c455bfeef76af649b87f75380a4511405baea633c1e4912fd84aff7b61e99716f0231d244c9cfeda1fafd7d718963e6a0c674ed705e9b1b4f76b + languageName: node + linkType: hard + "@npmcli/fs@npm:^3.1.0": version: 3.1.0 resolution: "@npmcli/fs@npm:3.1.0" @@ -319,156 +326,159 @@ __metadata: languageName: node linkType: hard -"@polkadot-api/json-rpc-provider-proxy@npm:0.0.1": - version: 0.0.1 - resolution: "@polkadot-api/json-rpc-provider-proxy@npm:0.0.1" - checksum: cf8daf52ff6d92f26c6027f13ef5fbef9e512626e0225bc8408b79002cfd34fc17c5f2d856beebcb01aa5f84c93ccc8272f9264dc8349b7f6cb63845b30119b5 +"@polkadot-api/json-rpc-provider-proxy@npm:^0.1.0": + version: 0.1.0 + resolution: "@polkadot-api/json-rpc-provider-proxy@npm:0.1.0" + checksum: 3dcfa50dfa9c1b5654d97d818ae85042facfdf47b71c418f069d664eba149c6be10eb02a8e8de011ce8753a813e214fff195f45f55851b8cfc7f60138fe9dfb2 languageName: node linkType: hard -"@polkadot-api/json-rpc-provider@npm:0.0.1": +"@polkadot-api/json-rpc-provider@npm:0.0.1, @polkadot-api/json-rpc-provider@npm:^0.0.1": version: 0.0.1 resolution: "@polkadot-api/json-rpc-provider@npm:0.0.1" checksum: 1f315bdadcba7def7145011132e6127b983c6f91f976be217ad7d555bb96a67f3a270fe4a46e427531822c5d54d353d84a6439d112a99cdfc07013d3b662ee3c languageName: node linkType: hard -"@polkadot-api/metadata-builders@npm:0.0.1": - version: 0.0.1 - resolution: "@polkadot-api/metadata-builders@npm:0.0.1" +"@polkadot-api/metadata-builders@npm:0.3.2": + version: 0.3.2 + resolution: "@polkadot-api/metadata-builders@npm:0.3.2" dependencies: - "@polkadot-api/substrate-bindings": 0.0.1 - "@polkadot-api/utils": 0.0.1 - checksum: 7cf69e583e64f0ea1b90b141d9f61c4b0ba445daf87d4eba25bfcaa629c95cf4bbe6d89f5263dc495189fae0795c45810a004a2a8fbf59ece01ae71e1e049f17 + "@polkadot-api/substrate-bindings": 0.6.0 + "@polkadot-api/utils": 0.1.0 + checksum: e37a664ac2582048a0dd0357b378349f2165eb2f0902f7bc3aa7ec7b84735cba2b4103d36169089671c422caab30af00467cf2866c1456fc668f57ff1c8d3b55 languageName: node linkType: hard -"@polkadot-api/observable-client@npm:0.1.0": - version: 0.1.0 - resolution: "@polkadot-api/observable-client@npm:0.1.0" +"@polkadot-api/observable-client@npm:^0.3.0": + version: 0.3.2 + resolution: "@polkadot-api/observable-client@npm:0.3.2" dependencies: - "@polkadot-api/metadata-builders": 0.0.1 - "@polkadot-api/substrate-bindings": 0.0.1 - "@polkadot-api/substrate-client": 0.0.1 - "@polkadot-api/utils": 0.0.1 + "@polkadot-api/metadata-builders": 0.3.2 + "@polkadot-api/substrate-bindings": 0.6.0 + "@polkadot-api/utils": 0.1.0 peerDependencies: + "@polkadot-api/substrate-client": 0.1.4 rxjs: ">=7.8.0" - checksum: 694ee405f40ce47eb8d23dd2fc68359a5016c54ac530893a76e772a2d6a1a7c09c3a11d772b7c196af4faa29e98a443849334b97c6bf91af616990b4c7834caa + checksum: a559a815c11fe29c5ce1d69e132bbfb451abd1de3fa2c701fa60777388c3730fb86acd7f6e3d9580ae50a148c742d4562aca90070c04c70fa9d45f9d5148b448 languageName: node linkType: hard -"@polkadot-api/substrate-bindings@npm:0.0.1": - version: 0.0.1 - resolution: "@polkadot-api/substrate-bindings@npm:0.0.1" +"@polkadot-api/substrate-bindings@npm:0.6.0": + version: 0.6.0 + resolution: "@polkadot-api/substrate-bindings@npm:0.6.0" dependencies: "@noble/hashes": ^1.3.1 - "@polkadot-api/utils": 0.0.1 + "@polkadot-api/utils": 0.1.0 "@scure/base": ^1.1.1 scale-ts: ^1.6.0 - checksum: fc49e49ffe749fc6fab49eee1d10d47fcd1fa3a9b6ca4e7bbde4e9741b9e062cd4e9271fd86a2525095ff36bf33b95d57c51efb88635bb60b2c77fa9e83b2cd6 + checksum: c752d52dbea2b332357652b5475297ee6fa2f1ab8adffa7bd697522df5a42a0c358aec6f558523fd6f38ab20ab54ed0bda284c0c0424d917c1c68ef435dde4a4 languageName: node linkType: hard -"@polkadot-api/substrate-client@npm:0.0.1": - version: 0.0.1 - resolution: "@polkadot-api/substrate-client@npm:0.0.1" - checksum: 13dc05f1fce0d00241b48d262d691a740c65b107800cdfdf8d800333e9b3950932ce50a88bf65810892e43103bf57d1541c71538e68aa27b9aba55b389835b91 +"@polkadot-api/substrate-client@npm:^0.1.2": + version: 0.1.4 + resolution: "@polkadot-api/substrate-client@npm:0.1.4" + dependencies: + "@polkadot-api/json-rpc-provider": 0.0.1 + "@polkadot-api/utils": 0.1.0 + checksum: b975bdf030523ea7620ef58b50ca1d258266656f040a95fa7875a59535a935b05d23d893090fc1216b0e119327b2df329a1aaca84c8893f5924b9536d2ed8473 languageName: node linkType: hard -"@polkadot-api/utils@npm:0.0.1": - version: 0.0.1 - resolution: "@polkadot-api/utils@npm:0.0.1" - checksum: 11e67019cbf6dd39997d772edf14296c1b156d7a59c7726ce117b438ee85a5e50e305514a2a93cba87fdce1380fcf045931f2fb959df3a43bb327e77ac876148 +"@polkadot-api/utils@npm:0.1.0": + version: 0.1.0 + resolution: "@polkadot-api/utils@npm:0.1.0" + checksum: 55f39cf6949e54b763fc67e5132ae7d1095bf28f8413895dcec7e5778d9fe345b1ce9fe08f127c84f79fb9aedd51f045aa8ed84b2a72f4217047a91d2ecb4c27 languageName: node linkType: hard -"@polkadot/api-augment@npm:12.3.1, @polkadot/api-augment@npm:^12.3.1": - version: 12.3.1 - resolution: "@polkadot/api-augment@npm:12.3.1" +"@polkadot/api-augment@npm:12.4.2, @polkadot/api-augment@npm:^12.4.1": + version: 12.4.2 + resolution: "@polkadot/api-augment@npm:12.4.2" dependencies: - "@polkadot/api-base": 12.3.1 - "@polkadot/rpc-augment": 12.3.1 - "@polkadot/types": 12.3.1 - "@polkadot/types-augment": 12.3.1 - "@polkadot/types-codec": 12.3.1 + "@polkadot/api-base": 12.4.2 + "@polkadot/rpc-augment": 12.4.2 + "@polkadot/types": 12.4.2 + "@polkadot/types-augment": 12.4.2 + "@polkadot/types-codec": 12.4.2 "@polkadot/util": ^13.0.2 - tslib: ^2.6.2 - checksum: e4c9948631180199c78d7a780f6575c3bf52a50b107a60ae23e964d204ce0ef06a835ce16edcb76fc4b7e930c0d2fcd9d2714ad23858b80b38b645bf85b4577d + tslib: ^2.6.3 + checksum: 95ca6ad35b682918d989523ec25153dc1d4beab51b7dba2d8cf0a699b6337db85715dbe32bd704e47ffe964226ee2054def76f87f2c932f5d4ee2be0164c1131 languageName: node linkType: hard -"@polkadot/api-base@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/api-base@npm:12.3.1" +"@polkadot/api-base@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/api-base@npm:12.4.2" dependencies: - "@polkadot/rpc-core": 12.3.1 - "@polkadot/types": 12.3.1 + "@polkadot/rpc-core": 12.4.2 + "@polkadot/types": 12.4.2 "@polkadot/util": ^13.0.2 rxjs: ^7.8.1 - tslib: ^2.6.2 - checksum: 5562e4c1940e946ef9261e29bffe6f130f244ad740f3c677318ae6fe25e3fa5c875200c1598e9a571d960ab75166dff18fafd5dfc03251f9cff93b780b578cca + tslib: ^2.6.3 + checksum: 56c5933217f14e034db39c81f6fa308f2604507bbde820ca67f316ba6a390200dafade1d990ba4d6f1d2bedb94d567cb27435efe341dabf06af2388d457fc4b7 languageName: node linkType: hard -"@polkadot/api-cli@npm:^0.57.3": - version: 0.57.3 - resolution: "@polkadot/api-cli@npm:0.57.3" +"@polkadot/api-cli@npm:^0.57.4": + version: 0.57.4 + resolution: "@polkadot/api-cli@npm:0.57.4" dependencies: - "@polkadot/api": ^12.3.1 - "@polkadot/api-augment": ^12.3.1 + "@polkadot/api": ^12.4.1 + "@polkadot/api-augment": ^12.4.1 "@polkadot/keyring": ^13.0.2 - "@polkadot/types": ^12.3.1 + "@polkadot/types": ^12.4.1 "@polkadot/util": ^13.0.2 "@polkadot/util-crypto": ^13.0.2 tslib: ^2.6.2 yargs: ^17.7.2 bin: polkadot-js-api: runcli.mjs - checksum: 33a8a218609e08725c39cf8725073f7c992dd03158d3ca9bf7ebd5b783347de30140661250a7dd4c6a5c1a811716b4a74b92f741498ce0f2ed34bc91da874f60 + checksum: 970a5d40e3bbaa39031c3a6ac26faf9544212d2280b5a47df555659bc1375a32d6f0f93cad412926ac678a1b9e12ad913f7cca4265a1abf9b6dfd637ba74d759 languageName: node linkType: hard -"@polkadot/api-derive@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/api-derive@npm:12.3.1" +"@polkadot/api-derive@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/api-derive@npm:12.4.2" dependencies: - "@polkadot/api": 12.3.1 - "@polkadot/api-augment": 12.3.1 - "@polkadot/api-base": 12.3.1 - "@polkadot/rpc-core": 12.3.1 - "@polkadot/types": 12.3.1 - "@polkadot/types-codec": 12.3.1 + "@polkadot/api": 12.4.2 + "@polkadot/api-augment": 12.4.2 + "@polkadot/api-base": 12.4.2 + "@polkadot/rpc-core": 12.4.2 + "@polkadot/types": 12.4.2 + "@polkadot/types-codec": 12.4.2 "@polkadot/util": ^13.0.2 "@polkadot/util-crypto": ^13.0.2 rxjs: ^7.8.1 - tslib: ^2.6.2 - checksum: 85f69b7fa1aa37b8210c57ec7cdeb6dbdbda897ca9b64067e767ec944912f5b57440a6247131508c6a1916bfb8b3c80f06f28d56d05242bc783f3904c2723c07 + tslib: ^2.6.3 + checksum: a209e498772ea33fe587327196f13b9779b7054bd986c48c8efeb8fe9c298a375ef478c72fe39f0afec303d418859deb2d8822b554b55640caf1c06e12beeaf1 languageName: node linkType: hard -"@polkadot/api@npm:12.3.1, @polkadot/api@npm:^12.3.1": - version: 12.3.1 - resolution: "@polkadot/api@npm:12.3.1" +"@polkadot/api@npm:12.4.2, @polkadot/api@npm:^12.4.1, @polkadot/api@npm:^12.4.2": + version: 12.4.2 + resolution: "@polkadot/api@npm:12.4.2" dependencies: - "@polkadot/api-augment": 12.3.1 - "@polkadot/api-base": 12.3.1 - "@polkadot/api-derive": 12.3.1 + "@polkadot/api-augment": 12.4.2 + "@polkadot/api-base": 12.4.2 + "@polkadot/api-derive": 12.4.2 "@polkadot/keyring": ^13.0.2 - "@polkadot/rpc-augment": 12.3.1 - "@polkadot/rpc-core": 12.3.1 - "@polkadot/rpc-provider": 12.3.1 - "@polkadot/types": 12.3.1 - "@polkadot/types-augment": 12.3.1 - "@polkadot/types-codec": 12.3.1 - "@polkadot/types-create": 12.3.1 - "@polkadot/types-known": 12.3.1 + "@polkadot/rpc-augment": 12.4.2 + "@polkadot/rpc-core": 12.4.2 + "@polkadot/rpc-provider": 12.4.2 + "@polkadot/types": 12.4.2 + "@polkadot/types-augment": 12.4.2 + "@polkadot/types-codec": 12.4.2 + "@polkadot/types-create": 12.4.2 + "@polkadot/types-known": 12.4.2 "@polkadot/util": ^13.0.2 "@polkadot/util-crypto": ^13.0.2 eventemitter3: ^5.0.1 rxjs: ^7.8.1 - tslib: ^2.6.2 - checksum: 62d5a65db4b5c6ff7c128b1b2c984815e9a30b9e4eb5b16751bb39a31f015bfa30989c9df299bf87c16b95b4ff116a76d932d3f859d880062066d355181b7423 + tslib: ^2.6.3 + checksum: 763e24b6d65c6a573d5d02153b35be9a4f7fa76101e3ad163dbfb46d7c0cd27904d28e92058c405dcd5ea2585788663ccaae406da09479b4bce4496e8f8a6f11 languageName: node linkType: hard @@ -497,128 +507,128 @@ __metadata: languageName: node linkType: hard -"@polkadot/rpc-augment@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/rpc-augment@npm:12.3.1" +"@polkadot/rpc-augment@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/rpc-augment@npm:12.4.2" dependencies: - "@polkadot/rpc-core": 12.3.1 - "@polkadot/types": 12.3.1 - "@polkadot/types-codec": 12.3.1 + "@polkadot/rpc-core": 12.4.2 + "@polkadot/types": 12.4.2 + "@polkadot/types-codec": 12.4.2 "@polkadot/util": ^13.0.2 - tslib: ^2.6.2 - checksum: f24657e68c7434652d62423597cc58a9d711fca61a10417d0cd6e04b01212910552490654f6a12047396063960645e2f123dad3ea5c3f8b6a0cc3996e5e3b677 + tslib: ^2.6.3 + checksum: 0b329278b8b7217cdb87d451ed16e57f0d357db4e62f06d0315eea3f18db5be0078594dd0984896483f78c81d12e9bb62314c141d0a895f4e997ff49e981d2c5 languageName: node linkType: hard -"@polkadot/rpc-core@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/rpc-core@npm:12.3.1" +"@polkadot/rpc-core@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/rpc-core@npm:12.4.2" dependencies: - "@polkadot/rpc-augment": 12.3.1 - "@polkadot/rpc-provider": 12.3.1 - "@polkadot/types": 12.3.1 + "@polkadot/rpc-augment": 12.4.2 + "@polkadot/rpc-provider": 12.4.2 + "@polkadot/types": 12.4.2 "@polkadot/util": ^13.0.2 rxjs: ^7.8.1 - tslib: ^2.6.2 - checksum: cbeca4b6b6c1470504249e72b56496f4dc2758dadb5ba25df5351ad972d61f59f698c7c691ad8594aeab9b3760241f7fd1e2a725b27265ca4f21e682d753a874 + tslib: ^2.6.3 + checksum: 5a925296e14b4db61b1e37597934ad6a75b8cd7c195d5ef4a50dc200b453fdd86908770308076fe89364be280ad5777b187657b465486767baae67c163906258 languageName: node linkType: hard -"@polkadot/rpc-provider@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/rpc-provider@npm:12.3.1" +"@polkadot/rpc-provider@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/rpc-provider@npm:12.4.2" dependencies: "@polkadot/keyring": ^13.0.2 - "@polkadot/types": 12.3.1 - "@polkadot/types-support": 12.3.1 + "@polkadot/types": 12.4.2 + "@polkadot/types-support": 12.4.2 "@polkadot/util": ^13.0.2 "@polkadot/util-crypto": ^13.0.2 "@polkadot/x-fetch": ^13.0.2 "@polkadot/x-global": ^13.0.2 "@polkadot/x-ws": ^13.0.2 - "@substrate/connect": 0.8.10 + "@substrate/connect": 0.8.11 eventemitter3: ^5.0.1 mock-socket: ^9.3.1 - nock: ^13.5.0 - tslib: ^2.6.2 + nock: ^13.5.4 + tslib: ^2.6.3 dependenciesMeta: "@substrate/connect": optional: true - checksum: 5dbbe3c91879fe43f9f4ebe5818f11f1ab20257276de956cee891c9ae4ad256468b81f5595b51192499e5ac3d07980f6d41cf450201fc0fdcaa3410fada56a5f + checksum: 029c2e7628271f5bb7ab4688adc14dcb3a6d13c00a2e1404f96f8a81188c51573d116e4c869b55faae54979afe319e4121404b956487784d52b5fd4a4c59bf26 languageName: node linkType: hard -"@polkadot/types-augment@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/types-augment@npm:12.3.1" +"@polkadot/types-augment@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/types-augment@npm:12.4.2" dependencies: - "@polkadot/types": 12.3.1 - "@polkadot/types-codec": 12.3.1 + "@polkadot/types": 12.4.2 + "@polkadot/types-codec": 12.4.2 "@polkadot/util": ^13.0.2 - tslib: ^2.6.2 - checksum: 3b5458af018ea1e6c65ed3358323c684c00aba261be7c2572d2adfd03e3689d40de7a60e9ebd78abf4af4abe587e382fe664c2ab83bddff3df8709713a8e09e3 + tslib: ^2.6.3 + checksum: 15c0d82e190e97dd91df068d3cd9717364fbdfb1c8f3f873ff5c9156b76ee0ae78550d935dd2f4cf7e47d477e7132575d1154c27f3eccb78676e001fea9945c1 languageName: node linkType: hard -"@polkadot/types-codec@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/types-codec@npm:12.3.1" +"@polkadot/types-codec@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/types-codec@npm:12.4.2" dependencies: "@polkadot/util": ^13.0.2 "@polkadot/x-bigint": ^13.0.2 - tslib: ^2.6.2 - checksum: ada3143d6a3742935acd027e2035769eee955c819f98c4661f16402d4466be9c25f3cdef1a2b6d8a811fdcb2b83791dbbe63f1a5eceaa1b5df0926e2ca5f2f9f + tslib: ^2.6.3 + checksum: d5357e70c1e48a3e34bfffdbc1c88d59fa014c984bcdb09fa61153ed0afe96908852c235112b215b26e4ff8cd86e7167fad8a73a57cc6da473ef5d0e214ee8ec languageName: node linkType: hard -"@polkadot/types-create@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/types-create@npm:12.3.1" +"@polkadot/types-create@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/types-create@npm:12.4.2" dependencies: - "@polkadot/types-codec": 12.3.1 + "@polkadot/types-codec": 12.4.2 "@polkadot/util": ^13.0.2 - tslib: ^2.6.2 - checksum: 2a712e43f593231ebc90b664a0ea2af71f63576b5a509c14b730c1d42d168ae63d4cedb8b598a9a8db6a778248a4dc6d6834a5d2d607816a9220dc72ca536e47 + tslib: ^2.6.3 + checksum: 44b2491a1feaba192f818e9ab3ace507e8c6d155f5451f3324342edee1bd2a21b65020a41c4e258ce4900c7209d7dffe7f31b1a9425dad44a26d7f28fe8480a5 languageName: node linkType: hard -"@polkadot/types-known@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/types-known@npm:12.3.1" +"@polkadot/types-known@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/types-known@npm:12.4.2" dependencies: "@polkadot/networks": ^13.0.2 - "@polkadot/types": 12.3.1 - "@polkadot/types-codec": 12.3.1 - "@polkadot/types-create": 12.3.1 + "@polkadot/types": 12.4.2 + "@polkadot/types-codec": 12.4.2 + "@polkadot/types-create": 12.4.2 "@polkadot/util": ^13.0.2 - tslib: ^2.6.2 - checksum: 8ea2a097b24a6c02c6b685d871c2bdaf788d13898c131ce824b125097b44a0676487b53a4b0c1c4c7c27cd100e668d3819bc0b6d1360603610b2dbd4780a153b + tslib: ^2.6.3 + checksum: 9410347693b1c14d8a1fa52e3a633b1345ceae34ca6e63f86dd87666bf752da47dff7f8aa60f249d640151025034078cf837c18929ac0d72d626159c045a1a02 languageName: node linkType: hard -"@polkadot/types-support@npm:12.3.1": - version: 12.3.1 - resolution: "@polkadot/types-support@npm:12.3.1" +"@polkadot/types-support@npm:12.4.2": + version: 12.4.2 + resolution: "@polkadot/types-support@npm:12.4.2" dependencies: "@polkadot/util": ^13.0.2 - tslib: ^2.6.2 - checksum: 40b509f8fa795d9e13a12a0db61de923e64e18f91df27c76ada6ebeb70f7b4d15ff478f74550590b4280e5de78d9598d36fa86a0c89e1d2e26e216cb3d8c29fc + tslib: ^2.6.3 + checksum: 77b96fa39717fbe0104b995a95b90e51e849f151de8d922e75f03a99c1b60aa1ee65029832b16e791692b4f3c17668ad8777fb6d2ce3f6019ca9aa01ba2135b0 languageName: node linkType: hard -"@polkadot/types@npm:12.3.1, @polkadot/types@npm:^12.3.1": - version: 12.3.1 - resolution: "@polkadot/types@npm:12.3.1" +"@polkadot/types@npm:12.4.2, @polkadot/types@npm:^12.4.1": + version: 12.4.2 + resolution: "@polkadot/types@npm:12.4.2" dependencies: "@polkadot/keyring": ^13.0.2 - "@polkadot/types-augment": 12.3.1 - "@polkadot/types-codec": 12.3.1 - "@polkadot/types-create": 12.3.1 + "@polkadot/types-augment": 12.4.2 + "@polkadot/types-codec": 12.4.2 + "@polkadot/types-create": 12.4.2 "@polkadot/util": ^13.0.2 "@polkadot/util-crypto": ^13.0.2 rxjs: ^7.8.1 - tslib: ^2.6.2 - checksum: d1f9f8b9512f7cb8fdc56d2268b12f11e9e79e45dc7095d5d91252c857dad731da34927852e5756d189879c1f89b9d68af35b99ec8e61996e0a9be5bacd72393 + tslib: ^2.6.3 + checksum: 7916d6ce73bc36e03582113114df01677f0cbfb780349d630f0da7a3413da42dbf9e9d5c97abdfb1918d67f6954c06ea3380cb162297c26503aa18b220ecec9d languageName: node linkType: hard @@ -930,6 +940,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:~1.1.8": + version: 1.1.8 + resolution: "@scure/base@npm:1.1.8" + checksum: 1fc8a355ba68663c0eb430cf6a2c5ff5af790c347c1ba1953f344e8681ab37e37e2545e495f7f971b0245727d710fea8c1e57d232d0c6c543cbed4965c7596a1 + languageName: node + linkType: hard + "@scure/bip32@npm:1.4.0": version: 1.4.0 resolution: "@scure/bip32@npm:1.4.0" @@ -941,13 +958,13 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:1.3.0": - version: 1.3.0 - resolution: "@scure/bip39@npm:1.3.0" +"@scure/bip39@npm:1.4.0": + version: 1.4.0 + resolution: "@scure/bip39@npm:1.4.0" dependencies: - "@noble/hashes": ~1.4.0 - "@scure/base": ~1.1.6 - checksum: dbb0b27df753eb6c6380010b25cc9a9ea31f9cb08864fc51e69e5880ff7e2b8f85b72caea1f1f28af165e83b72c48dd38617e43fc632779d025b50ba32ea759e + "@noble/hashes": ~1.5.0 + "@scure/base": ~1.1.8 + checksum: 211f2c01361993bfe54c0e4949f290224381457c7f76d7cd51d6a983f3f4b6b9f85adfd0e623977d777ed80417a5fe729eb19dd34e657147810a0e58a8e7b9e0 languageName: node linkType: hard @@ -958,39 +975,39 @@ __metadata: languageName: node linkType: hard -"@substrate/connect-known-chains@npm:^1.1.4": - version: 1.1.4 - resolution: "@substrate/connect-known-chains@npm:1.1.4" - checksum: 235c732509391f12525ec740dbb8b8d4c5f56b7c7e71216c933e12974e0ad4f9664f7248a6d6db8b687c1c9fca9105398113ac7fd39515163ab6a9d5f7eba737 +"@substrate/connect-known-chains@npm:^1.1.5": + version: 1.3.0 + resolution: "@substrate/connect-known-chains@npm:1.3.0" + checksum: 217d8161cfdd67795509425a4dbd41c0a054f6197053abae1232ab95c111a5834f8d158b0bb6224c754e9b0a14c8e5b1a37b14abac320f729266c0ebe050f12e languageName: node linkType: hard -"@substrate/connect@npm:0.8.10": - version: 0.8.10 - resolution: "@substrate/connect@npm:0.8.10" +"@substrate/connect@npm:0.8.11": + version: 0.8.11 + resolution: "@substrate/connect@npm:0.8.11" dependencies: "@substrate/connect-extension-protocol": ^2.0.0 - "@substrate/connect-known-chains": ^1.1.4 - "@substrate/light-client-extension-helpers": ^0.0.6 - smoldot: 2.0.22 - checksum: 2ed22ff5eefc547f9c3a7547f166b20c844372802cf406e6511844ed2f813b091f515611a720847e1b78848af1156d5cba403c9423c4ad32e4009daf014150bc + "@substrate/connect-known-chains": ^1.1.5 + "@substrate/light-client-extension-helpers": ^1.0.0 + smoldot: 2.0.26 + checksum: c7c915ef51c43258f928323b8197b20f8dc3c14f5a5369b320a209df0037bd49aa5fee849486872bee22f40fced8be169e23a600d36b6f254d7e9e80ac2e1c9c languageName: node linkType: hard -"@substrate/light-client-extension-helpers@npm:^0.0.6": - version: 0.0.6 - resolution: "@substrate/light-client-extension-helpers@npm:0.0.6" +"@substrate/light-client-extension-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "@substrate/light-client-extension-helpers@npm:1.0.0" dependencies: - "@polkadot-api/json-rpc-provider": 0.0.1 - "@polkadot-api/json-rpc-provider-proxy": 0.0.1 - "@polkadot-api/observable-client": 0.1.0 - "@polkadot-api/substrate-client": 0.0.1 + "@polkadot-api/json-rpc-provider": ^0.0.1 + "@polkadot-api/json-rpc-provider-proxy": ^0.1.0 + "@polkadot-api/observable-client": ^0.3.0 + "@polkadot-api/substrate-client": ^0.1.2 "@substrate/connect-extension-protocol": ^2.0.0 - "@substrate/connect-known-chains": ^1.1.4 + "@substrate/connect-known-chains": ^1.1.5 rxjs: ^7.8.1 peerDependencies: smoldot: 2.x - checksum: a0cc169e6edf56cdbfd839a32487e31ad0bcb4cc9d4d50bac632c16f95d6ebf54638b268c1f7b8e651482e201f38411139a90071bc91268a2c01e5b50f39f338 + checksum: 12b2180c1b5fa9884588e7e94c095ba6bdd4bc386ca54c2bd2d58e8b606b361b04636ae0536b1eb4a18398e31d191d5949e3b3ba9b3a01d6592f425fb671881c languageName: node linkType: hard @@ -1038,12 +1055,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:22.4.1": - version: 22.4.1 - resolution: "@types/node@npm:22.4.1" +"@types/node@npm:22.5.4": + version: 22.5.4 + resolution: "@types/node@npm:22.5.4" dependencies: undici-types: ~6.19.2 - checksum: 341eb54867a3ec8eee7853ff9a9fc92d9f66305b70c9bc5db78492d51f4da3cd81e50c077f5d98eef1835fcbca00c58bb2a229ef56b0e377e48a3284401bf3f6 + checksum: 77ac225c38c428200036780036da0bc6764e2721cfa8f528c7e7da7cfefe01a32a5791e28a54efbeedbc977949058d7db902b2e00139298225d4686cee4ae6db languageName: node linkType: hard @@ -1228,14 +1245,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.7.4": - version: 1.7.4 - resolution: "axios@npm:1.7.4" +"axios@npm:^1.7.7": + version: 1.7.7 + resolution: "axios@npm:1.7.7" dependencies: follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: 0c17039a9acfe6a566fca8431ba5c1b455c83d30ea6157fec68a6722878fcd30f3bd32d172f6bee0c51fe75ca98e6414ddcd968a87b5606b573731629440bfaf + checksum: 882d4fe0ec694a07c7f5c1f68205eb6dc5a62aecdb632cc7a4a3d0985188ce3030e0b277e1a8260ac3f194d314ae342117660a151fabffdc5081ca0b5a8b47fe languageName: node linkType: hard @@ -1882,7 +1899,7 @@ __metadata: version: 0.0.0-use.local resolution: "humanode-e2e-tests-bash@workspace:utils/e2e-tests/bash" dependencies: - "@polkadot/api-cli": ^0.57.3 + "@polkadot/api-cli": ^0.57.4 languageName: unknown linkType: soft @@ -1890,13 +1907,13 @@ __metadata: version: 0.0.0-use.local resolution: "humanode-e2e-tests-ts@workspace:utils/e2e-tests/ts" dependencies: - "@polkadot/api": ^12.3.1 - "@types/node": 22.4.1 + "@polkadot/api": ^12.4.2 + "@types/node": 22.5.4 "@vitest/expect": ^2.0.5 - axios: ^1.7.4 + axios: ^1.7.7 ethers: ^6.13.2 typescript: ^5.5.4 - viem: ^2.19.7 + viem: ^2.21.3 vitest: ^2.0.5 languageName: unknown linkType: soft @@ -2255,14 +2272,14 @@ __metadata: languageName: node linkType: hard -"nock@npm:^13.5.0": - version: 13.5.4 - resolution: "nock@npm:13.5.4" +"nock@npm:^13.5.4": + version: 13.5.5 + resolution: "nock@npm:13.5.5" dependencies: debug: ^4.1.0 json-stringify-safe: ^5.0.1 propagate: ^2.0.0 - checksum: d31f924e34c87ae985edfb7b5a56e8a4dcfc3a072334ceb6d686326581f93090b3e23492663a64ce61b8df4f365b113231d926bc300bcfe9e5eb309c3e4b8628 + checksum: 91947b683992096a694140714323f11493b8ad9961c172e3e574c4801131fea259755e95c48e7e01527c14209967c20f151ff03b6bf6700471f0f76fa4071d32 languageName: node linkType: hard @@ -2648,12 +2665,12 @@ __metadata: languageName: node linkType: hard -"smoldot@npm:2.0.22": - version: 2.0.22 - resolution: "smoldot@npm:2.0.22" +"smoldot@npm:2.0.26": + version: 2.0.26 + resolution: "smoldot@npm:2.0.26" dependencies: ws: ^8.8.1 - checksum: 383bc6a5481190d64302fad56e9e4120a484885aee5543b268887de425708f04e8b3b3b69893333dfd9fd0e596f006afaa7c7ee5ff260c5d2be929c60302d385 + checksum: df1b27afae3ade7ee08947ca73f6e7afd450106b7ae4ff127ad7e71b7c20b01a2dc64135a07a7039aeeb23ad30fb549d7003c3131afa368f47125abf6837d919 languageName: node linkType: hard @@ -2827,6 +2844,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.6.3": + version: 2.7.0 + resolution: "tslib@npm:2.7.0" + checksum: 1606d5c89f88d466889def78653f3aab0f88692e80bb2066d090ca6112ae250ec1cfa9dbfaab0d17b60da15a4186e8ec4d893801c67896b277c17374e36e1d28 + languageName: node + linkType: hard + "typescript@npm:^5.5.4": version: 5.5.4 resolution: "typescript@npm:5.5.4" @@ -2879,15 +2903,15 @@ __metadata: languageName: node linkType: hard -"viem@npm:^2.19.7": - version: 2.19.7 - resolution: "viem@npm:2.19.7" +"viem@npm:^2.21.3": + version: 2.21.3 + resolution: "viem@npm:2.21.3" dependencies: "@adraffy/ens-normalize": 1.10.0 "@noble/curves": 1.4.0 "@noble/hashes": 1.4.0 "@scure/bip32": 1.4.0 - "@scure/bip39": 1.3.0 + "@scure/bip39": 1.4.0 abitype: 1.0.5 isows: 1.0.4 webauthn-p256: 0.0.5 @@ -2897,7 +2921,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 61e9bca6f38d510a8ce0308d6b093970e0d58ae45481fcea78bbfdefb0b2d8b651071dd940da07049b949a2cb4b5c005eca2fdee748139ea816edb4b7bc53a8e + checksum: d54bebbae0e666dd90ee7e73ebd60e58ff4c47b8574843b03104da6548d4b96caa080d261fd4f0175a108c0e4d618e1576bdd14fa84f342301ead530db7788e2 languageName: node linkType: hard