diff --git a/.github/workflows/rust-cargo-build.yml b/.github/workflows/rust-cargo-build.yml index 16a14cc..0859ee1 100644 --- a/.github/workflows/rust-cargo-build.yml +++ b/.github/workflows/rust-cargo-build.yml @@ -19,7 +19,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout sources - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 with: fetch-depth: 50 submodules: 'recursive' @@ -32,7 +32,7 @@ jobs: override: true - name: Rust Cache - uses: Swatinem/rust-cache@v2.7.3 + uses: Swatinem/rust-cache@v2.7.5 - name: cargo build run: cargo build --release diff --git a/.github/workflows/rust-cargo-deny.yml b/.github/workflows/rust-cargo-deny.yml index e47b374..7594ff2 100644 --- a/.github/workflows/rust-cargo-deny.yml +++ b/.github/workflows/rust-cargo-deny.yml @@ -20,10 +20,10 @@ jobs: steps: - name: Checkout Sources - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 - name: Run cargo-deny - uses: EmbarkStudios/cargo-deny-action@v1 + uses: EmbarkStudios/cargo-deny-action@v2 with: command: check ${{ matrix.checks }} diff --git a/.github/workflows/rust-clippy.yml b/.github/workflows/rust-clippy.yml index 7d86f88..9dec14f 100644 --- a/.github/workflows/rust-clippy.yml +++ b/.github/workflows/rust-clippy.yml @@ -19,7 +19,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout sources - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 with: fetch-depth: 50 submodules: 'recursive' @@ -32,7 +32,7 @@ jobs: override: true - name: Rust Cache - uses: Swatinem/rust-cache@v2.7.3 + uses: Swatinem/rust-cache@v2.7.5 - name: cargo clippy run: cargo clippy --all-targets -- -D warnings -D clippy::pedantic -D clippy::correctness -D clippy::complexity -D clippy::perf diff --git a/.github/workflows/rust-fmt.yml b/.github/workflows/rust-fmt.yml index 0d7757b..22bb4f4 100644 --- a/.github/workflows/rust-fmt.yml +++ b/.github/workflows/rust-fmt.yml @@ -19,7 +19,7 @@ jobs: access_token: ${{ github.token }} - name: Checkout sources - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 with: fetch-depth: 50 submodules: 'recursive' diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index bba0a3d..64e1443 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -1,4 +1,4 @@ -name: Rust test +name: Kalatori Tests on: pull_request: @@ -9,36 +9,73 @@ on: jobs: check: - name: Cargo test - runs-on: ubuntu-latest + name: Cargo and TypeScript Tests + runs-on: ubuntu-latest steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.12.1 + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.12.1 with: - access_token: ${{ github.token }} + access_token: ${{ github.token }} - - name: Checkout sources - uses: actions/checkout@v4.2.0 + - name: Checkout sources + uses: actions/checkout@v4.2.0 with: - fetch-depth: 50 - submodules: 'recursive' + fetch-depth: 50 + submodules: recursive - - name: Install Rust stable toolchain - uses: actions-rs/toolchain@v1.0.7 + - name: Initialize Git Submodules + run: git submodule update --init --recursive + + - name: Verify directory structure + run: ls -R + + - name: Install Rust stable toolchain + uses: actions-rs/toolchain@v1.0.7 with: - profile: minimal - toolchain: stable - override: true + profile: minimal + toolchain: stable + override: true - - name: Install cargo-nextest - uses: baptiste0928/cargo-install@v3 + - name: Install cargo-nextest + uses: baptiste0928/cargo-install@v3 with: - crate: cargo-nextest - version: 0.9 + crate: cargo-nextest + version: 0.9 + + - name: Rust Cache + uses: Swatinem/rust-cache@v2.7.5 + + - name: Run Rust app in background with environment variables + run: | + export KALATORI_HOST="127.0.0.1:16726" + export KALATORI_SEED="bottom drive obey lake curtain smoke basket hold race lonely fit walk" + export KALATORI_RECIPIENT="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + export KALATORI_REMARK="test" + cargo build + nohup cargo r & + + - name: Wait for Rust app to start + run: sleep 120 + # Wait for the Rust app to start and then wait for the app to connect to RPC + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install Yarn package manager + run: npm install --global yarn + + - name: Install dependencies + working-directory: ./tests/kalatori-api-test-suite + run: yarn install --network-timeout 100000 - - name: Rust Cache - uses: Swatinem/rust-cache@v2.7.3 + - name: Run tests + working-directory: ./tests/kalatori-api-test-suite + env: + DAEMON_HOST: 'http://127.0.0.1:16726' + run: yarn test - - name: cargo nextest - run: cargo nextest run +# - name: Run Rust tests +# run: cargo nextest run diff --git a/.gitignore b/.gitignore index f5f61bb..9eb0cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ target +tests/kalatori-api-test-suite/node_modules/ *.db +*.txt +kalatori.toml # IDE + .vscode -.idea \ No newline at end of file +.idea diff --git a/CHANGELOG.md b/CHANGELOG.md index 0629fe5..4ee5b62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. +## [0.2.4] - 2024-10-21 + +### ⚡ Performance + +- Switched from the unmaintained `hex` crate to `const-hex`. + +### 🚜 Refactor + +- Moved all utility modules under the utils module. +- Removed all `mod.rs` files & added a lint rule to prevent them. + +## [0.2.3] - 2024-10-15 + +### 🚀 Features + +- Server health call implementation + ## [0.2.2] - 2024-10-10 ### 🚀 Features @@ -15,7 +32,7 @@ All notable changes to this project will be documented in this file. ## [0.2.1] - 2024-10-07 -Making the order request work according to specs in the [specs](https://alzymologist.github.io/kalatori-api/#/). +Making the order request work according to specs in the [specs](https://alzymologist.github.io/kalatori-api/#/). Using the tests from [kalatori-api-test-suite]() in order to validate. Added git cliff and configuration for it to generate CHANGELOG like this one, see [CONTRIBUTING.md](CONTRIBUTING.md) @@ -31,5 +48,3 @@ Added git cliff and configuration for it to generate CHANGELOG like this one, se ### ⚙️ Miscellaneous Tasks - Resolve conflicts - - diff --git a/Cargo.lock b/Cargo.lock index f1c10d3..b714dc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,19 +4,13 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -110,12 +104,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "anyhow" -version = "1.0.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" - [[package]] name = "approx" version = "0.5.1" @@ -147,33 +135,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "async-trait" -version = "0.1.82" +name = "async-lock" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", + "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "async-trait" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", @@ -204,9 +197,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", @@ -217,21 +210,20 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] [[package]] name = "axum-macros" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00c055ee2d014ae5981ce1016374e8213682aa14d9bf40e48ab48b5f3ef20eaa" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -243,7 +235,7 @@ dependencies = [ "addr2line", "cfg-if", "libc", - "miniz_oxide 0.8.0", + "miniz_oxide", "object", "rustc-demangle", "windows-targets", @@ -273,15 +265,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -336,12 +319,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -350,9 +327,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -362,18 +339,16 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.20" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bcde016d64c21da4be18b655631e5ab6d3107607e71a73a9f53eb48aae23fb" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ - "jobserver", - "libc", "shlex", ] @@ -391,9 +366,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -401,26 +376,27 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", + "terminal_size", ] [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -451,6 +427,28 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-hex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -591,7 +589,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -621,7 +619,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -667,7 +665,7 @@ checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek", "ed25519", - "hashbrown", + "hashbrown 0.14.5", "hex", "rand_core", "sha2", @@ -693,15 +691,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -719,22 +708,37 @@ dependencies = [ ] [[package]] -name = "external-memory-tools" -version = "0.1.1" +name = "event-listener" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf172ba7bfe5412e03c4dfd7d8e4b5f1e6cd0b7087fd61fa274b73f87ad94854" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] -name = "fastrand" -version = "2.1.1" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "external-memory-tools" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf172ba7bfe5412e03c4dfd7d8e4b5f1e6cd0b7087fd61fa274b73f87ad94854" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] @@ -778,12 +782,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -792,21 +796,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -846,13 +835,12 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -861,9 +849,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -871,49 +859,38 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -923,9 +900,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -982,22 +959,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" - -[[package]] -name = "git2" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" -dependencies = [ - "bitflags 2.6.0", - "libc", - "libgit2-sys", - "log", - "url", -] +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "group" @@ -1010,25 +974,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -1040,10 +985,10 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.4.1" +name = "hashbrown" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -1108,9 +1053,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1120,14 +1065,13 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", "http", "http-body", "httparse", @@ -1136,60 +1080,22 @@ dependencies = [ "pin-project-lite", "smallvec", "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", ] [[package]] name = "hyper-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", - "futures-channel", "futures-util", "http", "http-body", "hyper", "pin-project-lite", - "socket2", "tokio", - "tower", "tower-service", - "tracing", ] [[package]] @@ -1237,12 +1143,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -1269,12 +1175,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ipnet" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" - [[package]] name = "is_debug" version = "1.0.1" @@ -1313,29 +1213,11 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "jsonrpsee" -version = "0.23.2" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b089779ad7f80768693755a031cc14a7766aba707cbe886674e3f79e9b7e47" +checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" dependencies = [ "jsonrpsee-core", "jsonrpsee-types", @@ -1344,9 +1226,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.23.2" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08163edd8bcc466c33d79e10f695cdc98c00d1e6ddfb95cec41b6b0279dd5432" +checksum = "548125b159ba1314104f5bb5f38519e03a41862786aa3925cf349aae9cdd546e" dependencies = [ "base64", "futures-util", @@ -1367,13 +1249,11 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.23.2" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79712302e737d23ca0daa178e752c9334846b08321d439fd89af9a384f8c830b" +checksum = "f2882f6f8acb9fdaec7cefc4fd607119a9bd709831df7d7672a1d3b644628280" dependencies = [ - "anyhow", "async-trait", - "beef", "futures-timer", "futures-util", "jsonrpsee-types", @@ -1389,11 +1269,10 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.23.2" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c465fbe385238e861fdc4d1c85e04ada6c1fd246161d26385c1b311724d2af" +checksum = "a178c60086f24cc35bb82f57c651d0d25d99c4742b4d335de04e97fa1f08a8a1" dependencies = [ - "beef", "http", "serde", "serde_json", @@ -1402,9 +1281,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.23.2" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c28759775f5cb2f1ea9667672d3fe2b0e701d1f4b7b67954e60afe7fd058b5e" +checksum = "0fe322e0896d0955a3ebdd5bf813571c53fea29edd713bc315b76620b327e86d" dependencies = [ "http", "jsonrpsee-client-transport", @@ -1415,9 +1294,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -1427,23 +1306,21 @@ dependencies = [ [[package]] name = "kalatori" -version = "0.2.2" +version = "0.2.4" dependencies = [ "ahash", + "async-lock", "axum", "axum-macros", "clap", + "const-hex", "frame-metadata", - "futures", - "hex", "indoc", "jsonrpsee", - "lazy_static", "mnemonic-external", "names", "parity-scale-codec", "primitive-types", - "reqwest", "scale-info", "serde", "serde_json", @@ -1472,6 +1349,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kstring" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" +dependencies = [ + "static_assertions", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1483,33 +1369,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.158" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] -name = "libgit2-sys" -version = "0.16.2+1.7.2" +name = "libm" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libz-sys" -version = "1.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" @@ -1572,16 +1440,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", - "simd-adler32", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -1589,6 +1447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -1622,23 +1481,6 @@ dependencies = [ "rand", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nodrop" version = "0.1.14" @@ -1687,6 +1529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1700,44 +1543,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl-probe" @@ -1745,18 +1562,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "overload" version = "0.1.1" @@ -1813,24 +1618,20 @@ dependencies = [ ] [[package]] -name = "parking_lot" -version = "0.11.2" +name = "parking" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ + "instant", "lock_api", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] @@ -1842,24 +1643,11 @@ dependencies = [ "cfg-if", "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", "winapi", ] -[[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 0.5.4", - "smallvec", - "windows-targets", -] - [[package]] name = "pbkdf2" version = "0.12.2" @@ -1877,22 +1665,22 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -1917,12 +1705,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - [[package]] name = "plot_icon" version = "0.3.0" @@ -1937,15 +1719,15 @@ dependencies = [ [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.4", + "miniz_oxide", ] [[package]] @@ -1985,13 +1767,29 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bitflags 2.6.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax 0.8.5", + "unarray", +] + [[package]] name = "quote" version = "1.0.37" @@ -2038,33 +1836,33 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "rand_xorshift" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "bitflags 1.3.2", + "rand_core", ] [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 2.6.0", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -2078,13 +1876,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2095,52 +1893,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.12.7" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-registry", -] +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rfc6979" @@ -2175,9 +1930,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc-hex" @@ -2209,9 +1964,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "log", "once_cell", @@ -2237,19 +1992,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-platform-verifier" @@ -2291,9 +2045,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -2338,9 +2092,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -2400,9 +2154,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -2440,14 +2194,14 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -2467,9 +2221,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2520,12 +2274,11 @@ dependencies = [ [[package]] name = "shadow-rs" -version = "0.28.0" +version = "0.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d75516bdaee8f640543ad1f6e292448c23ce57143f812c3736ab4b0874383df" +checksum = "2311e39772c00391875f40e34d43efef247b23930143a70ca5fbec9505937420" dependencies = [ "const_format", - "git2", "is_debug", "time", ] @@ -2592,7 +2345,7 @@ dependencies = [ "fxhash", "libc", "log", - "parking_lot 0.11.2", + "parking_lot", ] [[package]] @@ -2767,9 +2520,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", @@ -2787,30 +2540,6 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] [[package]] name = "tap" @@ -2819,36 +2548,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "tempfile" -version = "3.12.0" +name = "terminal_size" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ - "cfg-if", - "fastrand", - "once_cell", "rustix", "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -2916,10 +2642,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", - "bytes", "libc", "mio", - "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", @@ -2935,17 +2659,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", + "syn 2.0.82", ] [[package]] @@ -2981,7 +2695,7 @@ dependencies = [ "futures-io", "futures-sink", "futures-util", - "hashbrown", + "hashbrown 0.14.5", "pin-project-lite", "tokio", ] @@ -3006,11 +2720,12 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", + "kstring", "serde", "serde_spanned", "toml_datetime", @@ -3019,14 +2734,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", @@ -3063,7 +2778,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -3073,6 +2788,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", ] [[package]] @@ -3091,14 +2818,9 @@ dependencies = [ "time", "tracing", "tracing-core", + "tracing-log", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "twox-hash" version = "1.6.3" @@ -3129,11 +2851,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -3152,9 +2880,9 @@ dependencies = [ [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -3194,10 +2922,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "vcpkg" -version = "0.2.15" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" @@ -3215,103 +2943,17 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.77", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" - -[[package]] -name = "web-sys" -version = "0.3.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -3347,36 +2989,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -3461,9 +3073,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3495,7 +3107,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] [[package]] @@ -3515,5 +3127,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.82", ] diff --git a/Cargo.toml b/Cargo.toml index 05312fb..9d0db03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kalatori" authors = ["Alzymologist Oy "] -version = "0.2.2" +version = "0.2.4" edition = "2021" description = "A gateway daemon for Kalatori." license = "GPL-3.0-or-later" @@ -9,6 +9,7 @@ repository = "https://github.com/Alzymologist/Kalatori-backend" readme = true keywords = ["substrate", "blockchain", "finance", "service", "middleware"] categories = ["finance"] +rust-version = "1.82" [dependencies] axum = { version = "0.7", default-features = false, features = [ @@ -18,35 +19,45 @@ axum = { version = "0.7", default-features = false, features = [ "json", "matched-path", ] } -tracing-subscriber = { version = "0.3", default-features = false, features = [ - "smallvec", - "ansi", - "env-filter", - "time", -] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "time"] } ureq = { version = "2", default-features = false, features = ["json"] } names = { version = "0.14", default-features = false } tokio-util = { version = "0.7", features = ["rt"] } -tokio = { version = "1", features = ["full"] } -serde = { version = "1", features = ["derive"] } +tokio = { version = "1", features = ["rt-multi-thread", "signal", "time"] } +serde = { version = "1", features = ["derive", "rc"] } tracing = "0.1" scale-info = "2" axum-macros = "0.4" primitive-types = { version = "0.12", features = ["codec"] } -jsonrpsee = { version = "0.23", features = ["ws-client"] } +jsonrpsee = { version = "0.24", features = ["ws-client"] } thiserror = "1" frame-metadata = "16" -hex = "0.4" -parity-scale-codec = "3" -serde_json = "1" -sp-crypto-hashing = "0.1" -toml_edit = { version = "0.22", features = ["serde"]} +const-hex = "1" +codec = { package = "parity-scale-codec", version = "3", features = [ + "chain-error", + "derive", +] } +serde_json = { version = "1", features = ["raw_value"] } +hashing = { package = "sp-crypto-hashing", version = "0.1" } +toml_edit = { version = "0.22", default-features = false, features = [ + "serde", + "parse", + "perf", +] } sled = "0.34" -zeroize = "1.7" -clap = { version = "4", features = ["derive", "cargo", "string", "env"] } -shadow-rs = { version = "0.28", default-features = false } -futures = "0.3" +zeroize = "1" +clap = { version = "4", features = [ + "derive", + "cargo", + "env", + "string", + "wrap_help", + "deprecated", +] } +shadow-rs = { version = "0.35", default-features = false } ahash = "0.8" +indoc = "2" +async-lock = "3" substrate_parser = { git = "https://github.com/Alzymologist/substrate-parser" } substrate-constructor = { git = "https://github.com/Alzymologist/substrate-constructor" } @@ -54,18 +65,14 @@ mnemonic-external = { git = "https://github.com/Alzymologist/mnemonic-external" substrate-crypto-light = { git = "https://github.com/Alzymologist/substrate-crypto-light" } [build-dependencies] -shadow-rs = { version = "0.28", default-features = false, features = ["git2"] } - -[dev-dependencies] -reqwest = { version = "0.12", features = ["json"] } -lazy_static = "1" -indoc = "2" +shadow-rs = { version = "0.35", default-features = false } [profile.release] strip = true lto = true codegen-units = 1 panic = "abort" +overflow-checks = true [lints.rust] future_incompatible = "warn" @@ -76,10 +83,12 @@ unused = "warn" rust-2024-compatibility = { level = "warn", priority = -1 } [lints.clippy] +allow_attributes = "warn" shadow_reuse = "warn" shadow_same = "warn" shadow_unrelated = "warn" cargo_common_metadata = "warn" arithmetic_side_effects = "warn" +mod_module_files = "warn" # TODO: https://github.com/rust-lang/cargo/issues/12918 pedantic = { level = "warn", priority = -1 } diff --git a/build.rs b/build.rs index 51ceaac..e1c1eba 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,8 @@ use shadow_rs::{ - SdResult, BUILD_OS, BUILD_TARGET, BUILD_TARGET_ARCH, CARGO_MANIFEST_DIR, CARGO_TREE, - CARGO_VERSION, COMMIT_AUTHOR, COMMIT_DATE, COMMIT_DATE_2822, COMMIT_DATE_3339, COMMIT_EMAIL, - COMMIT_HASH, GIT_CLEAN, GIT_STATUS_FILE, LAST_TAG, PKG_DESCRIPTION, PKG_VERSION_MAJOR, - PKG_VERSION_MINOR, PKG_VERSION_PATCH, PKG_VERSION_PRE, TAG, + SdResult, BUILD_OS, BUILD_TARGET, BUILD_TARGET_ARCH, CARGO_MANIFEST_DIR, CARGO_METADATA, + CARGO_TREE, CARGO_VERSION, COMMIT_AUTHOR, COMMIT_DATE, COMMIT_DATE_2822, COMMIT_DATE_3339, + COMMIT_EMAIL, COMMIT_HASH, GIT_CLEAN, GIT_STATUS_FILE, LAST_TAG, PKG_DESCRIPTION, + PKG_VERSION_MAJOR, PKG_VERSION_MINOR, PKG_VERSION_PATCH, PKG_VERSION_PRE, TAG, }; fn main() -> SdResult<()> { @@ -12,6 +12,7 @@ fn main() -> SdResult<()> { BUILD_TARGET, BUILD_TARGET_ARCH, CARGO_MANIFEST_DIR, + CARGO_METADATA, CARGO_TREE, CARGO_VERSION, COMMIT_AUTHOR, diff --git a/docs/DATABASE.md b/docs/DATABASE.md new file mode 100644 index 0000000..00bac1d --- /dev/null +++ b/docs/DATABASE.md @@ -0,0 +1,37 @@ +Plan is to update the database scheme in a way that it will support the requirements we have as for the API specs and additional improvements of the deamon. + +## Tables +### Orders (`orders`) +- order - String: order identifier provided by the frontend +- payment_status - Enum: (pending|paid|timed_out). +- withdrawal_status - Enum: (waiting|failed|completed|forced|none). +- amount - u128: Order amount +- currency - String: Currency ticker ("DOT"|"USDC"|...). +- callback: String: Callback url for frontend order status update +- payment_account: [u8; 32]: Derived address for this order. +- recipient: [u8; 32]: Address that will receive the payout once the order is fulfilled. +- message: String|null: Optional parameter for failed orders. +- payment_page: String|null: Optional parameter for the frontend to redirect to a payment page. +- redirect_url: String|null: Optional parameter for the frontend to redirect once the order is repaid. +- death: u32: Expiry timestamp for the order. + +### Transactions (`transactions`) +- transaction_id - unique id generated by us to allow linking transaction to order +- order - String: order id to link transaction to order +- chain - String: identifier for the chain where transaction occurred +- block_number - Integer: Block number where the transaction is recorded. +- position_in_block - Integer: Position of the transaction within the block. +- timestamp - Timestamp: Timestamp of the transaction. +- transaction_bytes - String: Raw transaction data. +- sender - String: Address sending the transaction. +- recipient - String: Address receiving the transaction. +- amount - Float: transaction amount +- currency: String: Transaction currency +- type - Enum: Transaction type (payment|withdrawal) to distinguish between internal (withdrawal) and external (payment) transactions +- status - Enum: Transaction status (pending|finalized|failed). + +### Instance Metadata (`instance_info`) +- instance_id - String: instance id randomly generated, happy-octopus or similar shit +- version - String: daemon version (storing it just for consistency with ServerInfo struct) +- debug - String: Debug toggle +- kalatori_remark: String: Environment specific something, can be used for whatever diff --git a/src/arguments.rs b/src/arguments.rs index a955ceb..738dfd9 100644 --- a/src/arguments.rs +++ b/src/arguments.rs @@ -1,7 +1,7 @@ use crate::{ definitions::{api_v2::Timestamp, Chain}, error::{Error, SeedEnvError}, - logger, + utils::logger, }; use ahash::AHashMap; use clap::{Arg, ArgAction, Parser}; diff --git a/src/chain.rs b/src/chain.rs new file mode 100644 index 0000000..7f866b3 --- /dev/null +++ b/src/chain.rs @@ -0,0 +1,224 @@ +//! Everything related to actual interaction with blockchain + +use std::collections::HashMap; +use substrate_crypto_light::common::AccountId32; +use tokio::{ + sync::{mpsc, oneshot}, + time::{timeout, Duration}, +}; +use tokio_util::sync::CancellationToken; + +use crate::{ + definitions::{api_v2::OrderInfo, Chain}, + error::{ChainError, Error}, + signer::Signer, + state::State, + utils::task_tracker::TaskTracker, +}; + +pub mod definitions; +pub mod payout; +pub mod rpc; +pub mod tracker; +pub mod utils; + +use crate::definitions::api_v2::{Health, RpcInfo, ServerHealth}; +use definitions::{ChainRequest, ChainTrackerRequest, WatchAccount}; +use tracker::start_chain_watch; + +/// Logging filter +pub const MODULE: &str = module_path!(); + +/// Wait this long before forgetting about stuck chain watcher +const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(120000); + +/// RPC server handle +#[derive(Clone, Debug)] +pub struct ChainManager { + pub tx: mpsc::Sender, +} + +impl ChainManager { + /// Run once to start all chain connections; this should be very robust, if manager fails + /// - all modules should be restarted, probably. + pub fn ignite( + chain: Vec, + state: State, + signer: Signer, + task_tracker: TaskTracker, + cancellation_token: CancellationToken, + ) -> Result { + let (tx, mut rx) = mpsc::channel(1024); + + let mut watch_chain = HashMap::new(); + + let mut currency_map = HashMap::new(); + + // Create a channel for receiving RPC status updates + let (rpc_update_tx, mut rpc_update_rx) = mpsc::channel(1024); + + // start network monitors + for c in chain { + if c.endpoints.is_empty() { + return Err(Error::EmptyEndpoints(c.name)); + } + let (chain_tx, chain_rx) = mpsc::channel(1024); + watch_chain.insert(c.name.clone(), chain_tx.clone()); + + // this MUST assert that there are no duplicates in requested assets + if let Some(ref a) = c.native_token { + if let Some(_) = currency_map.insert(a.name.clone(), c.name.clone()) { + return Err(Error::DuplicateCurrency(a.name.clone())); + } + } + for a in &c.asset { + if let Some(_) = currency_map.insert(a.name.clone(), c.name.clone()) { + return Err(Error::DuplicateCurrency(a.name.clone())); + } + } + + start_chain_watch( + c, + chain_tx.clone(), + chain_rx, + state.interface(), + signer.interface(), + task_tracker.clone(), + cancellation_token.clone(), + rpc_update_tx.clone(), + ); + } + + task_tracker + .clone() + .spawn("Blockchain connections manager", async move { + let mut rpc_statuses: HashMap<(String, String), Health> = HashMap::new(); + + + // start requests engine + loop { + tokio::select! { + Some(request) = rx.recv() => { + match request { + ChainRequest::WatchAccount(request) => { + if let Some(chain) = currency_map.get(&request.currency) { + if let Some(receiver) = watch_chain.get(chain) { + let _unused = receiver + .send(ChainTrackerRequest::WatchAccount(request)) + .await; + } else { + let _unused = request + .res + .send(Err(ChainError::InvalidChain(chain.to_string()))); + } + } else { + let _unused = request + .res + .send(Err(ChainError::InvalidCurrency(request.currency))); + } + } + ChainRequest::Reap(request) => { + if let Some(chain) = currency_map.get(&request.currency) { + if let Some(receiver) = watch_chain.get(chain) { + let _unused = + receiver.send(ChainTrackerRequest::Reap(request)).await; + } else { + let _unused = request + .res + .send(Err(ChainError::InvalidChain(chain.to_string()))); + } + } else { + let _unused = request + .res + .send(Err(ChainError::InvalidCurrency(request.currency))); + } + } + ChainRequest::Shutdown(res) => { + for (name, chain) in watch_chain.drain() { + let (tx, rx) = oneshot::channel(); + if chain.send(ChainTrackerRequest::Shutdown(tx)).await.is_ok() { + if timeout(SHUTDOWN_TIMEOUT, rx).await.is_err() { + tracing::error!("Chain monitor for {name} took too much time to wind down, probably it was frozen. Discarding it."); + }; + } + } + let _ = res.send(()); + break; + } + ChainRequest::GetConnectedRpcs(res_tx) => { + // Collect the RpcInfo from rpc_statuses + let connected_rpcs: Vec = rpc_statuses.iter().map(|((chain_name, rpc_url), status)| { + RpcInfo { + chain_name: chain_name.clone(), + rpc_url: rpc_url.clone(), + status: *status, + } + }).collect(); + let _ = res_tx.send(connected_rpcs); + } + } + } + Some(rpc_update) = rpc_update_rx.recv() => { + rpc_statuses.insert( + (rpc_update.chain_name.clone(), rpc_update.rpc_url.clone()), + rpc_update.status, + ); + } + else => break, + } + } + + Ok("Chain manager is shutting down") + }); + + Ok(Self { tx }) + } + + pub async fn add_invoice( + &self, + id: String, + order: OrderInfo, + recipient: AccountId32, + ) -> Result<(), ChainError> { + let (res, rx) = oneshot::channel(); + self.tx + .send(ChainRequest::WatchAccount(WatchAccount::new( + id, order, recipient, res, + )?)) + .await + .map_err(|_| ChainError::MessageDropped)?; + rx.await.map_err(|_| ChainError::MessageDropped)? + } + + pub async fn get_connected_rpcs(&self) -> Result, Error> { + let (res_tx, res_rx) = oneshot::channel(); + self.tx + .send(ChainRequest::GetConnectedRpcs(res_tx)) + .await + .map_err(|_| Error::Fatal)?; + res_rx.await.map_err(|_| Error::Fatal) + } + + pub async fn reap( + &self, + id: String, + order: OrderInfo, + recipient: AccountId32, + ) -> Result<(), ChainError> { + let (res, rx) = oneshot::channel(); + self.tx + .send(ChainRequest::Reap(WatchAccount::new( + id, order, recipient, res, + )?)) + .await + .map_err(|_| ChainError::MessageDropped)?; + rx.await.map_err(|_| ChainError::MessageDropped)? + } + + pub async fn shutdown(&self) -> () { + let (tx, rx) = oneshot::channel(); + let _unused = self.tx.send(ChainRequest::Shutdown(tx)).await; + let _ = rx.await; + () + } +} diff --git a/src/chain/definitions.rs b/src/chain/definitions.rs index cc7f8ab..d1ade60 100644 --- a/src/chain/definitions.rs +++ b/src/chain/definitions.rs @@ -1,22 +1,21 @@ //! Common objects for chain interaction system -use jsonrpsee::ws_client::WsClient; -use primitive_types::H256; -use substrate_crypto_light::common::{AccountId32, AsBase58}; -use tokio::sync::oneshot; - use crate::{ chain::{ rpc::{asset_balance_at_account, system_balance_at_account}, tracker::ChainWatcher, }, definitions::{ - api_v2::{OrderInfo, Timestamp}, + api_v2::{OrderInfo, RpcInfo, Timestamp}, Balance, }, - error::{ChainError, NotHex}, + error::{ChainError, NotHexError}, utils::unhex, }; +use jsonrpsee::ws_client::WsClient; +use primitive_types::H256; +use substrate_crypto_light::common::{AccountId32, AsBase58}; +use tokio::sync::oneshot; /// Abstraction to distinguish block hash from many other H256 things #[derive(Debug, Clone)] @@ -25,14 +24,14 @@ pub struct BlockHash(pub primitive_types::H256); impl BlockHash { /// Convert block hash to RPC-friendly format pub fn to_string(&self) -> String { - format!("0x{}", hex::encode(&self.0)) + format!("0x{}", const_hex::encode(&self.0)) } /// Convert string returned by RPC to typesafe block /// /// TODO: integrate nicely with serde pub fn from_str(s: &str) -> Result { - let block_hash_raw = unhex(&s, NotHex::BlockHash)?; + let block_hash_raw = unhex(&s, NotHexError::BlockHash)?; Ok(BlockHash(H256( block_hash_raw .try_into() @@ -89,6 +88,7 @@ pub enum ChainRequest { WatchAccount(WatchAccount), Reap(WatchAccount), Shutdown(oneshot::Sender<()>), + GetConnectedRpcs(oneshot::Sender>), } #[derive(Debug)] diff --git a/src/chain/mod.rs b/src/chain/mod.rs deleted file mode 100644 index 67cfed8..0000000 --- a/src/chain/mod.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! Everything related to actual interaction with blockchain - -use std::collections::HashMap; - -use substrate_crypto_light::common::AccountId32; -use tokio::{ - sync::{mpsc, oneshot}, - time::{timeout, Duration}, -}; -use tokio_util::sync::CancellationToken; - -use crate::{ - definitions::{api_v2::OrderInfo, Chain}, - error::{ChainError, Error}, - signer::Signer, - state::State, - task_tracker::TaskTracker, -}; - -pub mod definitions; -pub mod payout; -pub mod rpc; -pub mod tracker; -pub mod utils; - -use definitions::{ChainRequest, ChainTrackerRequest, WatchAccount}; -use tracker::start_chain_watch; - -/// Logging filter -pub const MODULE: &str = module_path!(); - -/// Wait this long before forgetting about stuck chain watcher -const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(120000); - -/// RPC server handle -#[derive(Clone, Debug)] -pub struct ChainManager { - pub tx: tokio::sync::mpsc::Sender, -} - -impl ChainManager { - /// Run once to start all chain connections; this should be very robust, if manager fails - /// - all modules should be restarted, probably. - pub fn ignite( - chain: Vec, - state: State, - signer: Signer, - task_tracker: TaskTracker, - cancellation_token: CancellationToken, - ) -> Result { - let (tx, mut rx) = mpsc::channel(1024); - - let mut watch_chain = HashMap::new(); - - let mut currency_map = HashMap::new(); - - // start network monitors - for c in chain { - if c.endpoints.is_empty() { - return Err(Error::EmptyEndpoints(c.name)); - } - let (chain_tx, chain_rx) = mpsc::channel(1024); - watch_chain.insert(c.name.clone(), chain_tx.clone()); - - // this MUST assert that there are no duplicates in requested assets - if let Some(ref a) = c.native_token { - if let Some(_) = currency_map.insert(a.name.clone(), c.name.clone()) { - return Err(Error::DuplicateCurrency(a.name.clone())); - } - } - for a in &c.asset { - if let Some(_) = currency_map.insert(a.name.clone(), c.name.clone()) { - return Err(Error::DuplicateCurrency(a.name.clone())); - } - } - - start_chain_watch( - c, - chain_tx.clone(), - chain_rx, - state.interface(), - signer.interface(), - task_tracker.clone(), - cancellation_token.clone(), - ); - } - - task_tracker - .clone() - .spawn("Blockchain connections manager", async move { - - // start requests engine - while let Some(request) = rx.recv().await { - match request { - ChainRequest::WatchAccount(request) => { - if let Some(chain) = currency_map.get(&request.currency) { - if let Some(receiver) = watch_chain.get(chain) { - let _unused = receiver - .send(ChainTrackerRequest::WatchAccount(request)) - .await; - } else { - let _unused = request - .res - .send(Err(ChainError::InvalidChain(chain.to_string()))); - } - } else { - let _unused = request - .res - .send(Err(ChainError::InvalidCurrency(request.currency))); - } - } - ChainRequest::Reap(request) => { - if let Some(chain) = currency_map.get(&request.currency) { - if let Some(receiver) = watch_chain.get(chain) { - let _unused = - receiver.send(ChainTrackerRequest::Reap(request)).await; - } else { - let _unused = request - .res - .send(Err(ChainError::InvalidChain(chain.to_string()))); - } - } else { - let _unused = request - .res - .send(Err(ChainError::InvalidCurrency(request.currency))); - } - } - ChainRequest::Shutdown(res) => { - for (name, chain) in watch_chain.drain() { - let (tx, rx) = oneshot::channel(); - if chain.send(ChainTrackerRequest::Shutdown(tx)).await.is_ok() { - if timeout(SHUTDOWN_TIMEOUT, rx).await.is_err() { - tracing::error!("Chain monitor for {name} took too much time to wind down, probably it was frozen. Discarding it."); - }; - } - } - let _ = res.send(()); - break; - } - } - } - - Ok("Chain manager is shutting down".into()) - }); - - Ok(Self { tx }) - } - - pub async fn add_invoice( - &self, - id: String, - order: OrderInfo, - recipient: AccountId32, - ) -> Result<(), ChainError> { - let (res, rx) = oneshot::channel(); - self.tx - .send(ChainRequest::WatchAccount(WatchAccount::new( - id, order, recipient, res, - )?)) - .await - .map_err(|_| ChainError::MessageDropped)?; - rx.await.map_err(|_| ChainError::MessageDropped)? - } - - pub async fn reap( - &self, - id: String, - order: OrderInfo, - recipient: AccountId32, - ) -> Result<(), ChainError> { - let (res, rx) = oneshot::channel(); - self.tx - .send(ChainRequest::Reap(WatchAccount::new( - id, order, recipient, res, - )?)) - .await - .map_err(|_| ChainError::MessageDropped)?; - rx.await.map_err(|_| ChainError::MessageDropped)? - } - - pub async fn shutdown(&self) -> () { - let (tx, rx) = oneshot::channel(); - let _unused = self.tx.send(ChainRequest::Shutdown(tx)).await; - let _ = rx.await; - () - } -} diff --git a/src/chain/payout.rs b/src/chain/payout.rs index 19a4859..607d64d 100644 --- a/src/chain/payout.rs +++ b/src/chain/payout.rs @@ -113,7 +113,7 @@ pub async fn payout( .send_this_signed::<(), RuntimeMetadataV15>(&chain.metadata)? .ok_or(ChainError::NothingToSend)?; - send_stuff(&client, &format!("0x{}", hex::encode(extrinsic))).await?; + send_stuff(&client, &format!("0x{}", const_hex::encode(extrinsic))).await?; // TODO obvious } diff --git a/src/chain/rpc.rs b/src/chain/rpc.rs index 1816224..3e9061a 100644 --- a/src/chain/rpc.rs +++ b/src/chain/rpc.rs @@ -13,21 +13,21 @@ use crate::{ api_v2::{AssetId, TokenKind}, Balance, }, - error::{ChainError, NotHex}, + error::{ChainError, NotHexError}, utils::unhex, }; +use codec::{DecodeAll, Encode}; use frame_metadata::{ v15::{RuntimeMetadataV15, StorageEntryMetadata, StorageEntryType}, RuntimeMetadata, }; +use hashing::twox_128; use jsonrpsee::core::client::{ClientT, Subscription, SubscriptionClientT}; use jsonrpsee::rpc_params; use jsonrpsee::ws_client::WsClient; -use parity_scale_codec::{DecodeAll, Encode}; use scale_info::{form::PortableForm, PortableRegistry, TypeDef, TypeDefPrimitive}; use serde::Deserialize; use serde_json::{Number, Value}; -use sp_crypto_hashing::twox_128; use std::{collections::HashMap, fmt::Debug}; use substrate_crypto_light::common::AccountId32; use substrate_parser::{ @@ -98,8 +98,8 @@ pub async fn get_keys_from_storage( let mut keys_vec = Vec::new(); let storage_key_prefix = format!( "0x{}{}", - hex::encode(twox_128(prefix.as_bytes())), - hex::encode(twox_128(storage_name.as_bytes())) + const_hex::encode(twox_128(prefix.as_bytes())), + const_hex::encode(twox_128(storage_name.as_bytes())) ); let count = 10; // TODO make full scan just in case @@ -198,7 +198,7 @@ pub async fn metadata( .map_err(ChainError::Client)?; match metadata_request { Value::String(x) => { - let metadata_request_raw = unhex(&x, NotHex::Metadata)?; + let metadata_request_raw = unhex(&x, NotHexError::Metadata)?; let maybe_metadata_raw = Option::>::decode_all(&mut &metadata_request_raw[..]) .map_err(|_| ChainError::RawMetadataNotDecodeable)?; if let Some(meta_v15_bytes) = maybe_metadata_raw { @@ -320,8 +320,8 @@ pub async fn assets_set_at_block( if let Value::String(string_key) = key { let value_fetch = get_value_from_storage(client, string_key, block).await?; if let Value::String(ref string_value) = value_fetch { - let key_data = unhex(string_key, NotHex::StorageKey)?; - let value_data = unhex(string_value, NotHex::StorageValue)?; + let key_data = unhex(string_key, NotHexError::StorageKey)?; + let value_data = unhex(string_value, NotHexError::StorageValue)?; let storage_entry = decode_as_storage_entry::<&[u8], (), RuntimeMetadataV15>( &key_data.as_ref(), @@ -384,11 +384,13 @@ pub async fn assets_set_at_block( TypeDef::Primitive(TypeDefPrimitive::U32) => { let key_assets_metadata = format!( "0x{}{}{}", - hex::encode(twox_128("Assets".as_bytes())), - hex::encode(twox_128( + const_hex::encode(twox_128( + "Assets".as_bytes() + )), + const_hex::encode(twox_128( "Metadata".as_bytes() )), - hex::encode(hashed_key_element( + const_hex::encode(hashed_key_element( &asset_id.encode(), hasher )) @@ -404,7 +406,7 @@ pub async fn assets_set_at_block( { let value_data = unhex( string_value, - NotHex::StorageValue, + NotHexError::StorageValue, )?; let value = decode_all_as_type::< &[u8], @@ -557,7 +559,7 @@ pub async fn asset_balance_at_account( let value_fetch = get_value_from_storage(client, &query.key, block).await?; if let Value::String(ref string_value) = value_fetch { - let value_data = unhex(string_value, NotHex::StorageValue)?; + let value_data = unhex(string_value, NotHexError::StorageValue)?; let value = decode_all_as_type::<&[u8], (), RuntimeMetadataV15>( &query.value_ty, &value_data.as_ref(), @@ -593,7 +595,7 @@ pub async fn system_balance_at_account( let value_fetch = get_value_from_storage(client, &query.key, block).await?; if let Value::String(ref string_value) = value_fetch { - let value_data = unhex(string_value, NotHex::StorageValue)?; + let value_data = unhex(string_value, NotHexError::StorageValue)?; let value = decode_all_as_type::<&[u8], (), RuntimeMetadataV15>( &query.value_ty, &value_data.as_ref(), @@ -659,10 +661,10 @@ async fn events_at_block( for key in keys_array { if let Value::String(key) = key { let data_from_storage = get_value_from_storage(client, &key, block).await?; - let key_bytes = unhex(&key, NotHex::StorageValue)?; + let key_bytes = unhex(&key, NotHexError::StorageValue)?; let value_bytes = if let Value::String(data_from_storage) = data_from_storage { - unhex(&data_from_storage, NotHex::StorageValue)? + unhex(&data_from_storage, NotHexError::StorageValue)? } else { return Err(ChainError::StorageValueFormat(data_from_storage)); }; @@ -725,7 +727,7 @@ pub async fn current_block_number( let block_number_query = block_number_query(metadata)?; let fetched_value = get_value_from_storage(client, &block_number_query.key, block).await?; if let Value::String(hex_data) = fetched_value { - let value_data = unhex(&hex_data, NotHex::StorageValue)?; + let value_data = unhex(&hex_data, NotHexError::StorageValue)?; let value = decode_all_as_type::<&[u8], (), RuntimeMetadataV15>( &block_number_query.value_ty, &value_data.as_ref(), diff --git a/src/chain/tracker.rs b/src/chain/tracker.rs index 4c36649..ec929a9 100644 --- a/src/chain/tracker.rs +++ b/src/chain/tracker.rs @@ -1,10 +1,9 @@ //! A tracker that follows individual chain -use std::{collections::HashMap, time::SystemTime}; - use frame_metadata::v15::RuntimeMetadataV15; use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; use serde_json::Value; +use std::{collections::HashMap, time::SystemTime}; use substrate_parser::{AsMetadata, ShortSpecs}; use tokio::{ sync::mpsc, @@ -12,6 +11,7 @@ use tokio::{ }; use tokio_util::sync::CancellationToken; +use crate::definitions::api_v2::{Health, RpcInfo}; use crate::{ chain::{ definitions::{BlockHash, ChainTrackerRequest, Invoice}, @@ -26,7 +26,7 @@ use crate::{ error::ChainError, signer::Signer, state::State, - task_tracker::TaskTracker, + utils::task_tracker::TaskTracker, }; #[allow(clippy::too_many_lines)] @@ -38,6 +38,7 @@ pub fn start_chain_watch( signer: Signer, task_tracker: TaskTracker, cancellation_token: CancellationToken, + rpc_update_tx: mpsc::Sender, ) { task_tracker .clone() @@ -51,9 +52,30 @@ pub fn start_chain_watch( if shutdown || cancellation_token.is_cancelled() { break; } + + let _ = rpc_update_tx.send(RpcInfo { + chain_name: chain.name.clone(), + rpc_url: endpoint.clone(), + status: Health::Degraded, + }).await; + if let Ok(client) = WsClientBuilder::default().build(endpoint).await { + let _ = rpc_update_tx.send(RpcInfo { + chain_name: chain.name.clone(), + rpc_url: endpoint.clone(), + status: Health::Ok, + }).await; + // prepare chain - let watcher = match ChainWatcher::prepare_chain(&client, chain.clone(), &mut watched_accounts, endpoint, chain_tx.clone(), state.interface(), task_tracker.clone()) + let watcher = match ChainWatcher::prepare_chain( + &client, + chain.clone(), + &mut watched_accounts, + endpoint, + chain_tx.clone(), + state.interface(), + task_tracker.clone(), + ) .await { Ok(a) => a, @@ -155,7 +177,7 @@ pub fn start_chain_watch( let signer_for_reaper = signer.interface(); task_tracker.clone().spawn(format!("Initiate payout for order {}", id.clone()), async move { payout(rpc, Invoice::from_request(request), reap_state_handle, watcher_for_reaper, signer_for_reaper).await; - Ok(format!("Payout attempt for order {id} terminated").into()) + Ok(format!("Payout attempt for order {id} terminated")) }); } ChainTrackerRequest::Shutdown(res) => { @@ -165,9 +187,15 @@ pub fn start_chain_watch( } } } + } else { + let _ = rpc_update_tx.send(RpcInfo { + chain_name: chain.name.clone(), + rpc_url: endpoint.clone(), + status: Health::Critical, + }).await; } } - Ok(format!("Chain {} monitor shut down", chain.name).into()) + Ok(format!("Chain {} monitor shut down", chain.name)) }); } @@ -295,7 +323,7 @@ impl ChainWatcher { } // this should reset chain monitor on timeout; // but if this breaks, it means that the latter is already down either way - Ok(format!("Block watch at {rpc} stopped").into()) + Ok(format!("Block watch at {rpc} stopped")) }); Ok(chain) diff --git a/src/chain/utils.rs b/src/chain/utils.rs index 60f548f..461e178 100644 --- a/src/chain/utils.rs +++ b/src/chain/utils.rs @@ -1,14 +1,14 @@ //! Utils to process chain data without accessing the chain use crate::{chain::definitions::BlockHash, definitions::api_v2::AssetId, error::ChainError}; +use codec::Encode; use frame_metadata::{ v14::StorageHasher, v15::{RuntimeMetadataV15, StorageEntryMetadata, StorageEntryType}, }; -use parity_scale_codec::Encode; +use hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64}; use scale_info::{form::PortableForm, TypeDef, TypeDefPrimitive}; use serde_json::{Map, Value}; -use sp_crypto_hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64}; use substrate_constructor::{ fill_prepare::{ prepare_type, EraToFill, PrimitiveToFill, RegularPrimitiveToFill, SpecialTypeToFill, @@ -886,9 +886,11 @@ pub fn whole_key_u32_value( TypeDef::Primitive(TypeDefPrimitive::U32) => { return Ok(format!( "0x{}{}{}", - hex::encode(twox_128(prefix.as_bytes())), - hex::encode(twox_128(storage_name.as_bytes())), - hex::encode(hashed_key_element( + const_hex::encode(twox_128(prefix.as_bytes())), + const_hex::encode(twox_128( + storage_name.as_bytes() + )), + const_hex::encode(hashed_key_element( &entered_data.encode(), hasher )) @@ -1083,8 +1085,8 @@ pub fn pallet_index(metadata: &RuntimeMetadataV15, name: &str) -> Option { pub fn storage_key(prefix: &str, storage_name: &str) -> String { format!( "0x{}{}", - hex::encode(twox_128(prefix.as_bytes())), - hex::encode(twox_128(storage_name.as_bytes())) + const_hex::encode(twox_128(prefix.as_bytes())), + const_hex::encode(twox_128(storage_name.as_bytes())) ) } diff --git a/src/database.rs b/src/database.rs index 6eabe71..96e6e0c 100644 --- a/src/database.rs +++ b/src/database.rs @@ -14,10 +14,10 @@ use crate::{ Version, }, error::{DbError, Error}, - task_tracker::TaskTracker, + utils::task_tracker::TaskTracker, }; +use codec::{Decode, Encode}; use names::{Generator, Name}; -use parity_scale_codec::{Decode, Encode}; use std::time::SystemTime; use substrate_crypto_light::common::AccountId32; use tokio::sync::{mpsc, oneshot}; @@ -278,7 +278,7 @@ impl Database { drop(database.flush()); - Ok("Database server is shutting down".into()) + Ok("Database server is shutting down") }); Ok(Self { tx }) diff --git a/src/definitions.rs b/src/definitions.rs index 927fce3..720f750 100644 --- a/src/definitions.rs +++ b/src/definitions.rs @@ -78,7 +78,7 @@ pub fn decimal_exponent_product(decimals: api_v2::Decimals) -> f64 { pub mod api_v2 { use std::collections::HashMap; - use parity_scale_codec::{Decode, Encode}; + use codec::{Decode, Encode}; use serde::{Deserialize, Serialize, Serializer}; pub const AMOUNT: &str = "amount"; @@ -176,6 +176,7 @@ pub mod api_v2 { pub enum WithdrawalStatus { Waiting, Failed, + Forced, Completed, } @@ -185,24 +186,23 @@ pub mod api_v2 { pub supported_currencies: HashMap, } - #[allow(dead_code)] // TODO: Use this for health response? #[derive(Debug, Serialize)] - struct ServerHealth { - server_info: ServerInfo, - connected_rpcs: Vec, - status: Health, + pub struct ServerHealth { + pub server_info: ServerInfo, + pub connected_rpcs: Vec, + pub status: Health, } - #[derive(Debug, Serialize)] - struct RpcInfo { - rpc_url: String, - chain_name: String, - status: Health, + #[derive(Debug, Serialize, Clone)] + pub struct RpcInfo { + pub rpc_url: String, + pub chain_name: String, + pub status: Health, } - #[derive(Debug, Serialize)] + #[derive(Debug, Serialize, Clone, PartialEq, Copy)] #[serde(rename_all = "lowercase")] - enum Health { + pub enum Health { Ok, Degraded, Critical, diff --git a/src/error.rs b/src/error.rs index 004689e..7ad03e3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,12 @@ use crate::{ arguments::{OLD_SEED, SEED}, definitions::api_v2::OrderStatus, + utils::task_tracker::TaskName, }; +use codec::Error as ScaleError; use frame_metadata::v15::RuntimeMetadataV15; use jsonrpsee::core::ClientError; use mnemonic_external::error::ErrorWordList; -use parity_scale_codec::Error as ScaleError; use serde_json::Error as JsonError; use serde_json::Value; use sled::Error as DatabaseError; @@ -58,8 +59,11 @@ pub enum Error { #[error("failed to initialize the asynchronous runtime")] Runtime(#[source] IoError), - #[error("failed to parse given filter directives for the logger ({0:?})")] - LoggerDirectives(String, #[source] ParseError), + #[error("failed to parse given filter directives for the logger")] + LoggerDirectives(#[from] ParseError), + + #[error("failed to complete {0}")] + Task(TaskName, #[source] TaskError), #[error("receiver account couldn't be parsed")] RecipientAccount(#[from] CryptoError), @@ -81,6 +85,10 @@ pub enum SeedEnvError { SeedNotPresent, } +#[derive(Debug, Error)] +#[expect(clippy::module_name_repetitions)] +pub enum TaskError {} + #[derive(Debug, Error)] #[allow(clippy::module_name_repetitions)] pub enum ChainError { @@ -372,7 +380,7 @@ pub enum ServerError { #[allow(clippy::module_name_repetitions)] pub enum UtilError { #[error("...")] - NotHex(NotHex), + NotHex(NotHexError), } #[derive(Debug, Error)] @@ -392,7 +400,7 @@ pub enum SignerError { } #[derive(Debug, Eq, PartialEq, thiserror::Error)] -pub enum NotHex { +pub enum NotHexError { #[error("block hash string isn't a valid hexadecimal")] BlockHash, @@ -428,6 +436,12 @@ mod pretty_cause { impl Display for Wrapper<'_, T> { fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.write_str("\n ")?; + + Display::fmt(&self.0, f)?; + + f.write_str(".")?; + let Some(cause) = self.0.source() else { // If an error has no source, print nothing. return Ok(()); @@ -504,13 +518,21 @@ mod pretty_cause { }; #[test] - fn empty() { - assert!(TestError::empty().pretty_cause().to_string().is_empty()); + fn no_cause() { + assert_eq!( + TestError::no_source().pretty_cause().to_string(), + "\n TestError(0)." + ); } #[test] fn single() { - const MESSAGE: &str = "\n\nCaused by: TestError(0)."; + const MESSAGE: &str = indoc::indoc! {" + + TestError(1). + + Caused by: TestError(0)." + }; assert_eq!(TestError::nested(1).pretty_cause().to_string(), MESSAGE); } @@ -518,7 +540,10 @@ mod pretty_cause { #[test] fn multiple() { const MESSAGE: &str = indoc::indoc! {" - \n\nCaused by: + + TestError(3). + + Caused by: 0: TestError(2). 1: TestError(1). 2: TestError(0)." @@ -529,10 +554,17 @@ mod pretty_cause { #[test] fn overload() { - let message = TestError::nested(OVERLOAD + 5).pretty_cause().to_string(); + let message = TestError::nested(OVERLOAD.saturating_add(5)) + .pretty_cause() + .to_string(); let mut expected_message = String::with_capacity(message.len()); - expected_message.push_str("\n\nCaused by:"); + expected_message.push_str(indoc::indoc! {" + + TestError(10004). + + Caused by:" + }); for number in 0..=OVERLOAD { write!( @@ -547,7 +579,8 @@ mod pretty_cause { } expected_message.push_str(indoc::indoc! {" - \n>9999: TestError(3). + + >9999: TestError(3). >9999: TestError(2). >9999: TestError(1). >9999: TestError(0)." @@ -563,7 +596,7 @@ mod pretty_cause { } impl TestError { - fn empty() -> Self { + fn no_source() -> Self { Self { source: None, number: 0, @@ -571,7 +604,7 @@ mod pretty_cause { } fn nested(nest: u16) -> Self { - let mut e = Self::empty(); + let mut e = Self::no_source(); for _ in 0..nest { e = Self { diff --git a/src/handlers/mod.rs b/src/handlers.rs similarity index 100% rename from src/handlers/mod.rs rename to src/handlers.rs diff --git a/src/handlers/health.rs b/src/handlers/health.rs index a606887..a3ae998 100644 --- a/src/handlers/health.rs +++ b/src/handlers/health.rs @@ -1,4 +1,4 @@ -use crate::definitions::api_v2::ServerStatus; +use crate::definitions::api_v2::{ServerHealth, ServerStatus}; use crate::state::State; use axum::{extract::State as ExtractState, http::StatusCode, Json}; @@ -18,12 +18,18 @@ pub async fn status( } pub async fn health( - ExtractState(_state): ExtractState, + ExtractState(state): ExtractState, ) -> ( [(axum::http::header::HeaderName, &'static str); 1], - Json, + Json, ) { - todo!(); + match state.server_health().await { + Ok(status) => ( + [(axum::http::header::CACHE_CONTROL, "no-store")], + Json(status), + ), + Err(_) => panic!("db connection is down, state is lost"), + } } pub async fn audit(ExtractState(_state): ExtractState) -> StatusCode { diff --git a/src/lib.rs b/src/lib.rs index de6ad9f..ef3382b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,11 @@ -pub mod arguments; -pub mod callback; -pub mod chain; -pub mod database; -pub mod definitions; -pub mod error; -pub mod handlers; -pub mod logger; -pub mod server; -pub mod shutdown; -pub mod signer; -pub mod state; -pub mod task_tracker; -pub mod utils; +mod arguments; +mod callback; +mod chain; +mod database; +mod definitions; +mod error; +mod handlers; +mod server; +mod signer; +mod state; +mod utils; diff --git a/src/main.rs b/src/main.rs index 100d9c8..9277f91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,73 +1,89 @@ use clap::Parser; -use std::{process::ExitCode, sync::Arc}; +use std::process::ExitCode; use substrate_crypto_light::common::{AccountId32, AsBase58}; -use tokio::{ - runtime::Runtime, - sync::{oneshot, RwLock}, -}; +use tokio::{runtime::Runtime, sync::oneshot}; use tokio_util::sync::CancellationToken; use tracing::Level; +use utils::{ + logger, + shutdown::{self, ShutdownNotification, ShutdownOutcome}, + task_tracker::TaskTracker, +}; -use kalatori::arguments::{CliArgs, Config, SeedEnvVars, DATABASE_DEFAULT}; -use kalatori::chain::ChainManager; -use kalatori::database::ConfigWoChains; -use kalatori::error::{Error, PrettyCause}; -use kalatori::logger; -use kalatori::shutdown::{set_panic_hook, ShutdownNotification, ShutdownReason}; -use kalatori::signer::Signer; -use kalatori::state::State; -use kalatori::task_tracker::TaskTracker; +mod arguments; +mod callback; +mod chain; +mod database; +mod definitions; +mod error; +mod handlers; +mod server; +mod signer; +mod state; +mod utils; + +use arguments::{CliArgs, Config, SeedEnvVars, DATABASE_DEFAULT}; +use chain::ChainManager; +use database::ConfigWoChains; +use error::{Error, PrettyCause}; +use signer::Signer; +use state::State; fn main() -> ExitCode { let shutdown_notification = ShutdownNotification::new(); // Sets the panic hook to print directly to the standard error because the logger isn't // initialized yet. - set_panic_hook(|panic| eprintln!("{panic}"), shutdown_notification.clone()); + shutdown::set_panic_hook(|panic| eprintln!("{panic}"), shutdown_notification.clone()); + + if let Err(error) = try_main(shutdown_notification.clone()) { + // TODO: https://github.com/rust-lang/rust/issues/92698 + // An equilibristic to conditionally print an error message without storing it as `String` + // on the heap. + let print = |message| { + if tracing::event_enabled!(Level::ERROR) { + tracing::error!("{message}"); + } else { + eprintln!("{message}"); + } + }; + + print(format_args!( + "Badbye! The daemon's got an error during the initialization:{}", + error.pretty_cause() + )); - match try_main(shutdown_notification) { - Ok(failed) => match *failed.blocking_read() { - ShutdownReason::UserRequested => { + ExitCode::FAILURE + } else { + match *shutdown_notification.outcome.read_blocking() { + ShutdownOutcome::UserRequested => { tracing::info!("Goodbye!"); ExitCode::SUCCESS } - ShutdownReason::UnrecoverableError => { - tracing::error!("Badbye! The daemon's shut down with errors."); + ShutdownOutcome::UnrecoverableError { panic } => { + tracing::error!( + "Badbye! The daemon's shut down with errors{}.", + if panic { " due to internal bugs" } else { "" } + ); ExitCode::FAILURE } - }, - Err(error) => { - let print = |message| { - if tracing::event_enabled!(Level::ERROR) { - tracing::error!("{message}"); - } else { - eprintln!("{message}"); - } - }; - - print(format_args!( - "Badbye! The daemon's got a fatal error:\n {error}.{}", - error.pretty_cause() - )); - - ExitCode::FAILURE } } } -fn try_main( - shutdown_notification: ShutdownNotification, -) -> Result>, Error> { +fn try_main(shutdown_notification: ShutdownNotification) -> Result<(), Error> { let cli_args = CliArgs::parse(); logger::initialize(cli_args.log)?; - set_panic_hook( + shutdown::set_panic_hook( |panic| tracing::error!("{panic}"), shutdown_notification.clone(), ); + tracing::info!("Kalatori {} is starting...", env!("CARGO_PKG_VERSION")); + let seed_env_vars = SeedEnvVars::parse()?; let config = Config::parse(cli_args.config)?; @@ -88,7 +104,7 @@ async fn async_try_main( remark: Option, config: Config, seed_env_vars: SeedEnvVars, -) -> Result>, Error> { +) -> Result<(), Error> { let database_path = if config.in_memory_db { if config.database.is_some() { tracing::warn!( @@ -103,13 +119,6 @@ async fn async_try_main( // Start services - tracing::info!( - "Kalatori {} by {} is starting on {}...", - env!("CARGO_PKG_VERSION"), - env!("CARGO_PKG_AUTHORS"), - config.host, - ); - let (task_tracker, error_rx) = TaskTracker::new(); let recipient = AccountId32::from_base58_string(&recipient_string) @@ -118,11 +127,8 @@ async fn async_try_main( let signer = Signer::init(recipient, task_tracker.clone(), seed_env_vars.seed)?; - let db = kalatori::database::Database::init( - database_path, - task_tracker.clone(), - config.account_lifetime, - )?; + let db = + database::Database::init(database_path, task_tracker.clone(), config.account_lifetime)?; let instance_id = db.initialize_server_info().await?; @@ -153,7 +159,7 @@ async fn async_try_main( )?) .map_err(|_| Error::Fatal)?; - let server = kalatori::server::new( + let server = server::new( shutdown_notification.token.clone(), config.host, state.interface(), @@ -163,27 +169,22 @@ async fn async_try_main( task_tracker.spawn("the server module", server); let shutdown_completed = CancellationToken::new(); - let mut shutdown_listener = tokio::spawn(kalatori::shutdown::listener( + let mut shutdown_listener = tokio::spawn(shutdown::listener( shutdown_notification.token.clone(), shutdown_completed.clone(), )); - // Main loop + tracing::info!("The initialization has been completed."); - Ok(tokio::select! { + // Start the main loop and wait for it to gracefully end or the early termination signal. + tokio::select! { biased; - reason = task_tracker.wait_with_notification(error_rx, shutdown_notification) => { + () = task_tracker.wait_and_shutdown(error_rx, shutdown_notification) => { shutdown_completed.cancel(); - shutdown_listener.await.expect("shutdown listener shouldn't panic")?; - reason - } - error = &mut shutdown_listener => { - return Err( - error - .expect("shutdown listener shouldn't panic") - .expect_err("shutdown listener should only complete on errors here") - ); + shutdown_listener.await } - }) + shutdown_listener_result = &mut shutdown_listener => shutdown_listener_result + } + .expect("shutdown listener shouldn't panic") } diff --git a/src/server.rs b/src/server.rs index 02701fe..5dbc999 100644 --- a/src/server.rs +++ b/src/server.rs @@ -46,7 +46,9 @@ pub async fn new( .await .map_err(|_| ServerError::TcpListenerBind(host))?; - Ok(async { + Ok(async move { + tracing::info!("The server is listening on {host}."); + axum::serve(listener, app) .with_graceful_shutdown(shutdown_notification.cancelled_owned()) .await diff --git a/src/signer.rs b/src/signer.rs index f024b71..ee6fb22 100644 --- a/src/signer.rs +++ b/src/signer.rs @@ -12,7 +12,7 @@ use crate::{ definitions::Entropy, error::{Error, SignerError}, - task_tracker::TaskTracker, + utils::task_tracker::TaskTracker, }; use mnemonic_external::{regular::InternalWordList, WordSet}; @@ -71,7 +71,7 @@ impl Signer { } } } - Ok("Signer module cleared and is shutting down!".into()) + Ok("Signer module cleared and is shutting down!") }); Ok(Self { tx }) diff --git a/src/state.rs b/src/state.rs index 91b414f..84cd716 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,18 +1,15 @@ use crate::{ chain::ChainManager, - database::ConfigWoChains, - database::Database, + database::{ConfigWoChains, Database}, definitions::api_v2::{ - CurrencyProperties, OrderCreateResponse, OrderInfo, OrderQuery, OrderResponse, OrderStatus, - ServerInfo, ServerStatus, + CurrencyProperties, Health, OrderCreateResponse, OrderInfo, OrderQuery, OrderResponse, + OrderStatus, RpcInfo, ServerHealth, ServerInfo, ServerStatus, }, error::{Error, OrderError}, signer::Signer, - task_tracker::TaskTracker, + utils::task_tracker::TaskTracker, }; - use std::collections::HashMap; - use substrate_crypto_light::common::{AccountId32, AsBase58}; use tokio::sync::oneshot; use tokio_util::sync::CancellationToken; @@ -82,7 +79,7 @@ impl State { .add_invoice(order, order_details, state.recipient) .await; } - Ok("All saved orders restored".into()) + Ok("All saved orders restored") }); loop { @@ -122,6 +119,15 @@ impl State { }; res.send(server_status).map_err(|_| Error::Fatal)?; } + StateAccessRequest::ServerHealth(res) => { + let connected_rpcs = state.chain_manager.get_connected_rpcs().await?; + let server_health = ServerHealth { + server_info: state.server_info.clone(), + connected_rpcs: connected_rpcs.clone(), + status: Self::overall_health(&connected_rpcs), + }; + res.send(server_health).map_err(|_| Error::Fatal)?; + } StateAccessRequest::OrderPaid(id) => { // Only perform actions if the record is saved in ledger match state.db.mark_paid(id.clone()).await { @@ -158,14 +164,29 @@ impl State { } } - Ok("State handler is shutting down".into()) + Ok("State handler is shutting down") }); Ok(Self { tx }) } + fn overall_health(connected_rpcs: &Vec) -> Health { + if connected_rpcs.iter().all(|rpc| rpc.status == Health::Ok) { + Health::Ok + } else if connected_rpcs.iter().any(|rpc| rpc.status == Health::Ok) { + Health::Degraded + } else { + Health::Critical + } + } + pub async fn connect_chain(&self, assets: HashMap) { - self.tx.send(StateAccessRequest::ConnectChain(assets)).await; + self.tx + .send(StateAccessRequest::ConnectChain(assets)) + .await + .unwrap_or_else(|e| { + tracing::error!("Failed to send ConnectChain request: {}", e); + }); } pub async fn order_status(&self, order: &str) -> Result { @@ -189,6 +210,15 @@ impl State { rx.await.map_err(|_| Error::Fatal) } + pub async fn server_health(&self) -> Result { + let (res, rx) = oneshot::channel(); + self.tx + .send(StateAccessRequest::ServerHealth(res)) + .await + .map_err(|_| Error::Fatal)?; + rx.await.map_err(|_| Error::Fatal) + } + pub async fn create_order(&self, order_query: OrderQuery) -> Result { let (res, rx) = oneshot::channel(); /* @@ -253,6 +283,7 @@ enum StateAccessRequest { res: oneshot::Sender, }, ServerStatus(oneshot::Sender), + ServerHealth(oneshot::Sender), OrderPaid(String), } diff --git a/src/task_tracker.rs b/src/task_tracker.rs deleted file mode 100644 index d37cd86..0000000 --- a/src/task_tracker.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::{ - error::{Error, PrettyCause}, - shutdown::{ShutdownNotification, ShutdownReason}, -}; -use std::{borrow::Cow, future::Future, sync::Arc}; -use tokio::{ - sync::{ - mpsc::{UnboundedReceiver, UnboundedSender}, - RwLock, - }, - task::JoinHandle, -}; - -#[derive(Clone)] -pub struct TaskTracker { - inner: tokio_util::task::TaskTracker, - error_tx: UnboundedSender<(Cow<'static, str>, Error)>, -} - -impl TaskTracker { - pub fn new() -> (Self, UnboundedReceiver<(Cow<'static, str>, Error)>) { - let (error_tx, error_rx) = tokio::sync::mpsc::unbounded_channel(); - let inner = tokio_util::task::TaskTracker::new(); - - inner.close(); - - (Self { inner, error_tx }, error_rx) - } - - pub fn spawn( - &self, - name: impl Into> + Send + 'static, - task: impl Future, Error>> + Send + 'static, - ) -> JoinHandle<()> { - let error_tx = self.error_tx.clone(); - - self.inner.spawn(async move { - match task.await { - Ok(shutdown_message) => { - if !shutdown_message.is_empty() { - tracing::info!("{shutdown_message}"); - } - } - Err(error) => error_tx.send((name.into(), error)).unwrap(), - } - }) - } - - pub async fn wait_with_notification( - self, - mut error_rx: UnboundedReceiver<(Cow<'static, str>, Error)>, - shutdown_notification: ShutdownNotification, // Pass the full ShutdownNotification struct - ) -> Arc> { - drop(self.error_tx); // Drop the error_tx to avoid deadlocks - - let mut failed = false; - - while let Some((from, error)) = error_rx.recv().await { - tracing::error!( - "Received a fatal error from {from}:\n {error:?}.{}", - error.pretty_cause() - ); - - if failed || !shutdown_notification.is_ignited() { - // Use is_ignited from ShutdownNotification - tracing::info!("Initializing the shutdown..."); - - failed = true; - - shutdown_notification.ignite().await; - } - } - - self.inner.wait().await; - - shutdown_notification.reason.clone() // Return the shutdown reason from ShutdownNotification - } -} diff --git a/src/utils.rs b/src/utils.rs index 8b931f5..a4e3019 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,13 @@ -use crate::error::{NotHex, UtilError}; +use crate::error::{NotHexError, UtilError}; -pub fn unhex(hex_data: &str, what_is_hex: NotHex) -> Result, UtilError> { +pub mod logger; +pub mod shutdown; +pub mod task_tracker; + +pub fn unhex(hex_data: &str, what_is_hex: NotHexError) -> Result, UtilError> { if let Some(stripped) = hex_data.strip_prefix("0x") { - hex::decode(stripped).map_err(|_| UtilError::NotHex(what_is_hex)) + const_hex::decode(stripped).map_err(|_| UtilError::NotHex(what_is_hex)) } else { - hex::decode(hex_data).map_err(|_| UtilError::NotHex(what_is_hex)) + const_hex::decode(hex_data).map_err(|_| UtilError::NotHex(what_is_hex)) } } diff --git a/src/logger.rs b/src/utils/logger.rs similarity index 84% rename from src/logger.rs rename to src/utils/logger.rs index 844e0a8..8c75112 100644 --- a/src/logger.rs +++ b/src/utils/logger.rs @@ -1,20 +1,20 @@ -use crate::{callback, chain, database, error::Error, server}; +use super::shutdown; +use crate::{callback, database, error::Error, server}; use tracing_subscriber::{fmt::time::UtcTime, EnvFilter}; const TARGETS: &[&str] = &[ callback::MODULE, database::MODULE, - chain::MODULE, server::MODULE, + shutdown::MODULE, env!("CARGO_PKG_NAME"), ]; const COMMA: &str = ","; const INFO: &str = "=info"; const OFF: &str = "off"; -pub fn initialize(directives: String) -> Result<(), Error> { - let filter = - EnvFilter::try_new(&directives).map_err(|e| Error::LoggerDirectives(directives, e))?; +pub fn initialize(directives: impl AsRef) -> Result<(), Error> { + let filter = EnvFilter::try_new(directives)?; tracing_subscriber::fmt() .with_timer(UtcTime::rfc_3339()) diff --git a/src/shutdown.rs b/src/utils/shutdown.rs similarity index 59% rename from src/shutdown.rs rename to src/utils/shutdown.rs index 1d089d3..404f79c 100644 --- a/src/shutdown.rs +++ b/src/utils/shutdown.rs @@ -1,46 +1,44 @@ +//! The shutdown module. +//! +//! Handles a graceful shutdown with an asynchronous runtime with respect of panics (by +//! incorporating a custom panic handler) & unrecoverable errors from another modules. + use crate::error::Error; +use async_lock::{RwLock, RwLockUpgradableReadGuard}; use std::{ fmt::{Display, Formatter, Result as FmtResult}, io::Result as IoResult, - panic::{self, PanicInfo}, - process, + panic::{self, PanicHookInfo}, sync::Arc, time::Duration, }; -use tokio::{signal, sync::RwLock, time}; +use tokio::{signal, time}; use tokio_util::sync::CancellationToken; +pub const MODULE: &str = module_path!(); + +const TIP_FUSE_SECS: u64 = 15; + #[derive(Clone)] -#[allow(clippy::module_name_repetitions)] +#[expect(clippy::module_name_repetitions)] pub struct ShutdownNotification { pub token: CancellationToken, - pub reason: Arc>, + pub outcome: Arc>, } impl ShutdownNotification { pub fn new() -> Self { Self { token: CancellationToken::new(), - reason: Arc::new(RwLock::new(ShutdownReason::UserRequested)), + outcome: Arc::new(RwLock::new(ShutdownOutcome::UserRequested)), } } - - pub fn is_ignited(&self) -> bool { - self.token.is_cancelled() - } - - pub async fn ignite(&self) { - *self.reason.write().await = ShutdownReason::UnrecoverableError; - self.token.cancel(); - } } pub async fn listener( shutdown_notification: CancellationToken, shutdown_completed: CancellationToken, ) -> Result<(), Error> { - const TIP_TIMEOUT_SECS: u64 = 30; - tokio::select! { biased; result = signal::ctrl_c() => { @@ -50,7 +48,9 @@ pub async fn listener( shutdown_notification.cancel(); } - () = shutdown_notification.cancelled() => {} + () = shutdown_notification.cancelled() => { + tracing::info!("The shutdown started by an unrecoverable error..."); + } } let shutdown_completed_clone = shutdown_completed.clone(); @@ -58,9 +58,10 @@ pub async fn listener( tokio::select! { biased; () = shutdown_completed_clone.cancelled() => {} - () = time::sleep(Duration::from_secs(TIP_TIMEOUT_SECS)) => { + () = time::sleep(Duration::from_secs(TIP_FUSE_SECS)) => { tracing::warn!( - "Send the shutdown signal one more time to kill the daemon instead of waiting for the graceful shutdown." + "Send the shutdown signal one more time to early terminate the daemon \ + instead of waiting for the graceful shutdown." ); } } @@ -72,15 +73,15 @@ pub async fn listener( result = signal::ctrl_c() => { process_signal(result)?; - tracing::info!("Received the second shutdown signal. Killing the daemon..."); + tracing::info!("Received the second shutdown signal. Terminating the daemon..."); - process::abort() + return Ok(()); } } tip.await.expect("tip task shouldn't panic"); - tracing::info!("The shutdown signal listener is shut down."); + tracing::debug!("The shutdown signal listener is shut down."); Ok(()) } @@ -88,16 +89,17 @@ pub async fn listener( fn process_signal(result: IoResult<()>) -> Result<(), Error> { result.map_err(Error::ShutdownSignal)?; - println!(); // Print shutdown log messages on the next line after the Control-C command. + // Print shutdown log messages on the next line after the Control-C command. + println!(); Ok(()) } #[derive(Clone, Copy)] -#[allow(clippy::module_name_repetitions)] -pub enum ShutdownReason { +#[expect(clippy::module_name_repetitions)] +pub enum ShutdownOutcome { UserRequested, - UnrecoverableError, + UnrecoverableError { panic: bool }, } pub fn set_panic_hook( @@ -105,27 +107,34 @@ pub fn set_panic_hook( shutdown_notification: ShutdownNotification, ) { panic::set_hook(Box::new(move |panic_info| { - let reason = *shutdown_notification.reason.blocking_read(); + let outcome = shutdown_notification.outcome.upgradable_read_blocking(); - let first = match reason { - ShutdownReason::UserRequested => false, - ShutdownReason::UnrecoverableError => { - *shutdown_notification.reason.blocking_write() = ShutdownReason::UnrecoverableError; - true - } + let first = if matches!( + *outcome, + ShutdownOutcome::UnrecoverableError { panic: true } + ) { + false + } else { + *RwLockUpgradableReadGuard::upgrade_blocking(outcome) = + ShutdownOutcome::UnrecoverableError { panic: true }; + + shutdown_notification.token.cancel(); + + true }; print(PrettyPanic { panic_info, first }); - - shutdown_notification.token.cancel(); })); } pub struct PrettyPanic<'a> { - panic_info: &'a PanicInfo<'a>, + panic_info: &'a PanicHookInfo<'a>, first: bool, } +// It looks like it's impossible to acquire `PanicInfo` outside of `panic::set_hook`, which +// could alter execution of other unit tests, so, without mocking the `panic_info` field, +// there's no way to test the `Display`ing. impl Display for PrettyPanic<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { f.write_str("A panic detected")?; @@ -149,6 +158,7 @@ impl Display for PrettyPanic<'_> { f.write_str(".")?; // Print the report request only on the first panic. + if self.first { f.write_str(concat!( "\n\nThis is a bug. Please report it at ", diff --git a/src/utils/task_tracker.rs b/src/utils/task_tracker.rs new file mode 100644 index 0000000..c70b821 --- /dev/null +++ b/src/utils/task_tracker.rs @@ -0,0 +1,217 @@ +//! The task tracker module. +//! +//! Contains utilities for orchestrating crucial initialization & loop tasks, and logic for +//! handling errors occurring in them. + +use super::shutdown::{ShutdownNotification, ShutdownOutcome}; +use crate::error::{Error, PrettyCause, TaskError}; +use async_lock::RwLockUpgradableReadGuard; +use std::{ + error::Error as StdError, + fmt::{Debug, Display}, + future::Future, +}; +use tokio::{ + sync::mpsc::{self, error::TrySendError, Receiver, Sender, UnboundedReceiver, UnboundedSender}, + task::JoinHandle, +}; +use tokio_util::task::TaskTracker as InnerTaskTracker; + +/// Needed to place [`TaskName`]s in error types. +pub trait Print: Display + Debug {} + +impl Print for T {} + +pub type TaskName = Box; + +fn create_closed() -> InnerTaskTracker { + let tt = InnerTaskTracker::new(); + + tt.close(); + + tt +} + +fn spawn_inner( + tt: &InnerTaskTracker, + name: impl Print + Send + 'static, + task: impl Future> + Send + 'static, + handler: impl FnOnce(T) + Send + 'static, + send_error: impl Fn((TaskName, E)) + Send + 'static, +) -> JoinHandle<()> { + tt.spawn(async move { + match task.await { + Ok(output) => handler(output), + Err(error) => send_error((Box::new(name), error)), + } + }) +} + +async fn wait_inner( + tt: InnerTaskTracker, + error_tx: S, + handler: impl Future>, +) -> Result<(), Error> { + // `self` holds the last `error_tx`, so we need to drop it; otherwise it'll create a + // deadlock on `error_rx.recv()` (see `wait_inner()` callers). + drop(error_tx); + + handler.await?; + + tt.wait().await; + + Ok(()) +} + +fn print_fatal_error(from: &TaskName, error: &(impl PrettyCause + Display)) { + tracing::error!( + "Received a fatal error from {from}:{}", + error.pretty_cause() + ); +} + +/// The main task tracker for processing the core main loop. +/// +/// Only 1 should be used across the program (see [`Self::wait_and_shutdown`]). Otherwise, the +/// shutdown behaviour is unknown. +#[derive(Clone)] +pub struct TaskTracker { + inner: InnerTaskTracker, + error_tx: UnboundedSender<(TaskName, Error)>, +} + +impl TaskTracker { + /// [`tokio::mpsc::UnboundedReceiver`] can't be cloned and hence isn't stored inside the + /// struct, so it's the caller's responsibility to take the receiver and then pass it to + /// [`Self::wait_and_shutdown`]. + pub fn new() -> (Self, UnboundedReceiver<(TaskName, Error)>) { + let (error_tx, error_rx) = mpsc::unbounded_channel(); + + ( + Self { + inner: create_closed(), + error_tx, + }, + error_rx, + ) + } + + /// Will panic on an error occurrence inside `task` if a receiver handle from + /// [`Self::new()`] has been closed/dropped before the occurrence. + pub fn spawn( + &self, + name: impl Print + Send + 'static, + task: impl Future> + Send + 'static, + ) -> JoinHandle<()> { + let error_tx = self.error_tx.clone(); + + spawn_inner( + &self.inner, + name, + task, + |shutdown_message| tracing::info!("{shutdown_message}"), + move |error| { + error_tx + .send(error) + .expect("receiver handle shouldn't be closed/dropped"); + }, + ) + } + + /// Starts the program main loop & waits until all tasks are finished. + /// + /// If any errors would occur in awaited tasks, `shutdown_notification` is triggered to shut + /// down all listening it tasks, and, eventually, the program. + pub async fn wait_and_shutdown( + self, + mut error_rx: UnboundedReceiver<(TaskName, Error)>, + shutdown_notification: ShutdownNotification, + ) { + wait_inner(self.inner, self.error_tx, async { + let mut no_errors = true; + + while let Some((from, error)) = error_rx.recv().await { + print_fatal_error(&from, &error); + + if no_errors { + let outcome = shutdown_notification.outcome.upgradable_read().await; + + if matches!(*outcome, ShutdownOutcome::UserRequested) { + *RwLockUpgradableReadGuard::upgrade(outcome).await = + ShutdownOutcome::UnrecoverableError { panic: false }; + + shutdown_notification.token.cancel(); + } + + no_errors = false; + } + } + + Ok(()) + }) + .await + .expect("this future shouldn't return errors"); + } +} + +type ErrorChannel = ( + Sender<(TaskName, TaskError)>, + Receiver<(TaskName, TaskError)>, +); + +/// The short-lived task tracker. +/// +/// Should be used for tracking temporal tasks (e.g. initialization ones). +#[expect(clippy::module_name_repetitions)] +pub struct ShortTaskTracker { + inner: InnerTaskTracker, + error_channel: ErrorChannel, +} + +impl ShortTaskTracker { + pub fn new() -> Self { + Self { + inner: create_closed(), + error_channel: mpsc::channel(1), + } + } + + pub fn spawn( + &self, + name: impl Print + Send + 'static, + task: impl Future> + Send + 'static, + ) -> JoinHandle<()> { + let error_tx = self.error_channel.0.clone(); + + spawn_inner( + &self.inner, + name, + task, + |()| (), + move |tn_and_error| { + if let Err( + TrySendError::Full((from, error)) | TrySendError::Closed((from, error)), + ) = error_tx.try_send(tn_and_error) + { + print_fatal_error(&from, &error); + }; + }, + ) + } + + /// Waits until all [`spawn`](Self::spawn)ed tasks are finished. + /// + /// If an error occurs in awaited tasks, this method immediately returns the first error. Do + /// note that it doesn't cancel unfinished tasks, they will continue running until + /// completion & log all occured errors. + pub async fn try_wait(mut self) -> Result<(), Error> { + wait_inner(self.inner, self.error_channel.0, async { + if let Some((from, error)) = self.error_channel.1.recv().await { + return Err(Error::Task(from, error)); + } + + Ok(()) + }) + .await + } +} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs deleted file mode 100644 index c06d18e..0000000 --- a/tests/integration_tests.rs +++ /dev/null @@ -1,179 +0,0 @@ -// ensure you have chopsticks installed: npm install -g @acala-network/chopsticks -// if running locally, ensure that you have no dangling processes (kalatori daemon, chopsticks) -// pkill -f kalatori; pkill -f chopsticks - -use kalatori::definitions::api_v2::{ServerStatus, TokenKind}; -use lazy_static::lazy_static; -use reqwest::Client; -use std::env; -use std::process::{Child, Command}; -use std::sync::{Mutex, Once}; -use tokio::time::{sleep, Duration}; - -static INIT: Once = Once::new(); -lazy_static! { - static ref CHOPSTICKS: Mutex> = Mutex::new(None); -} - -async fn start_chopsticks() -> std::io::Result { - let mut command = Command::new("npx"); - command.args(&[ - "@acala-network/chopsticks@latest", - "-c", - "chopsticks/pd-ah.yml", - ]); - let chopsticks = command.spawn()?; - sleep(Duration::from_secs(10)).await; // Give Chopsticks some time to start - Ok(chopsticks) -} - -async fn stop_chopsticks(chopsticks: &mut Child) -> std::io::Result<()> { - chopsticks.kill()?; - chopsticks.wait()?; - Ok(()) -} - -const KALATORI_REMARK: &str = "TEST_REMARK"; -const KALATORI_CARGO_PACKAGE_VERSION: &str = env!("CARGO_PKG_VERSION"); - -fn load_chain_config() { - env::set_var("KALATORI_CONFIG", "configs/chopsticks.toml"); - env::set_var("KALATORI_HOST", "127.0.0.1:16726"); - env::set_var( - "KALATORI_SEED", - "bottom drive obey lake curtain smoke basket hold race lonely fit walk", - ); - env::set_var("KALATORI_RPC", "ws://localhost:8000"); - env::set_var("KALATORI_DECIMALS", "12"); - env::set_var( - "KALATORI_RECIPIENT", - "5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV", - ); - env::set_var("KALATORI_REMARK", KALATORI_REMARK.to_string()); - // env::set_var("RUST_BACKTRACE", "1"); -} - -async fn start_daemon() -> std::io::Result { - let daemon = Command::new("target/debug/kalatori").spawn()?; - sleep(Duration::from_secs(10)).await; // Give the daemon some time to start - Ok(daemon) -} - -async fn stop_daemon(daemon: &mut Child) -> std::io::Result<()> { - daemon.kill()?; - daemon.wait()?; - Ok(()) -} - -struct TestContext { - daemon: Option, -} - -impl TestContext { - async fn new() -> Self { - // Start Chopsticks if not already started - INIT.call_once(|| { - tokio::spawn(async { - let chopsticks = start_chopsticks() - .await - .expect("Failed to start Chopsticks"); - let mut guard = CHOPSTICKS.lock().unwrap(); - *guard = Some(chopsticks); - }); - }); - - // Wait for Chopsticks to start - sleep(Duration::from_secs(3)).await; - - // Then start the daemon - load_chain_config(); - let daemon = start_daemon() - .await - .expect("Failed to start kalatori daemon"); - - TestContext { - daemon: Some(daemon), - } - } - - async fn drop_async(&mut self) { - if let Some(mut daemon) = self.daemon.take() { - let _ = stop_daemon(&mut daemon).await; - } - } -} -#[tokio::test] -async fn test_daemon_status_call() { - let mut context = TestContext::new().await; - - let client = Client::new(); - - let resp = client - .get("http://127.0.0.1:16726/v2/status") - .send() - .await - .expect("Failed to send request"); - - // Assert that the response status is 200 OK - assert!(resp.status().is_success()); - - let body = resp - .json::() - .await - .expect("Failed to parse response"); - - let body_str = body.to_string(); - let server_status: ServerStatus = - serde_json::from_str(&body_str).expect("Failed to deserialize ServerStatus"); - - assert_eq!( - server_status.server_info.version, - KALATORI_CARGO_PACKAGE_VERSION - ); - assert!(!server_status.server_info.instance_id.is_empty()); - assert_eq!(server_status.server_info.debug, true); - assert_eq!( - server_status.server_info.kalatori_remark, - Some(KALATORI_REMARK.into()) - ); - - assert!(!server_status.supported_currencies.is_empty()); - for (currency, properties) in server_status.supported_currencies { - assert!(!currency.is_empty()); - assert!(!properties.chain_name.is_empty()); - assert!(matches!( - properties.kind, - TokenKind::Native | TokenKind::Asset - )); - assert!(properties.decimals > 0); - assert!(!properties.rpc_url.is_empty()); - - if currency == "DOT" { - assert_eq!(properties.chain_name, "statemint"); - assert_eq!(properties.kind, TokenKind::Native); - assert_eq!(properties.decimals, 10); - assert_eq!(properties.rpc_url, "ws://localhost:8000"); - // those are wrong atm - } - } - - context.drop_async().await; -} - -// #[tokio::test] -// async fn test_daemon_health_call() { -// let mut context = TestContext::new().await; -// -// let client = Client::new(); -// -// let resp = client -// .get("http://127.0.0.1:16726/v2/health") -// .send() -// .await -// .expect("Failed to send request"); -// -// // Assert that the response status is 200 OK -// assert!(resp.status().is_success()); -// -// context.drop_async().await; -// } diff --git a/tests/kalatori-api-test-suite/.env b/tests/kalatori-api-test-suite/.env new file mode 100644 index 0000000..da248c9 --- /dev/null +++ b/tests/kalatori-api-test-suite/.env @@ -0,0 +1 @@ +DAEMON_HOST="http://127.0.0.1:16726" diff --git a/tests/kalatori-api-test-suite/README.md b/tests/kalatori-api-test-suite/README.md new file mode 100644 index 0000000..7b5627f --- /dev/null +++ b/tests/kalatori-api-test-suite/README.md @@ -0,0 +1,12 @@ +# BLACKBOX TEST SUITE FOR KALATORI + +This test suite is intended to be used against running kalatori instance. + +## Prerequisites +Ensure you have Node.js and Yarn installed on your machine. +A running instance of the Kalatori API that the tests can interact with. + +## Setup +1. install dependencies by runnin `yarn` +2. check `.env` file to ensure that variables are in sync with daemon you are testing against +3. run tests with `yarn test` diff --git a/tests/kalatori-api-test-suite/jest.config.js b/tests/kalatori-api-test-suite/jest.config.js new file mode 100644 index 0000000..f9d9d7b --- /dev/null +++ b/tests/kalatori-api-test-suite/jest.config.js @@ -0,0 +1,6 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/tests/**/*.test.ts'], + setupFiles: ['./setupEnv.js'] +}; diff --git a/tests/kalatori-api-test-suite/package.json b/tests/kalatori-api-test-suite/package.json new file mode 100644 index 0000000..c362547 --- /dev/null +++ b/tests/kalatori-api-test-suite/package.json @@ -0,0 +1,23 @@ +{ + "name": "kalatori-api-test-suite", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "jest" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "dotenv": "^16.4.5", + "@polkadot/api": "^12.4.1", + "@polkadot/util-crypto": "^13.0.2", + "@types/jest": "^29.5.12", + "@types/supertest": "^6.0.2", + "jest": "^29.7.0", + "supertest": "^7.0.0", + "ts-jest": "^29.2.4", + "typescript": "^5.5.4" + } +} diff --git a/tests/kalatori-api-test-suite/setupEnv.js b/tests/kalatori-api-test-suite/setupEnv.js new file mode 100644 index 0000000..f851825 --- /dev/null +++ b/tests/kalatori-api-test-suite/setupEnv.js @@ -0,0 +1 @@ +require('dotenv').config(); diff --git a/tests/kalatori-api-test-suite/src/polkadot.ts b/tests/kalatori-api-test-suite/src/polkadot.ts new file mode 100644 index 0000000..9099023 --- /dev/null +++ b/tests/kalatori-api-test-suite/src/polkadot.ts @@ -0,0 +1,51 @@ +import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; +import { cryptoWaitReady, decodeAddress, encodeAddress } from '@polkadot/util-crypto'; + +export async function updateAccountBalance(api: ApiPromise, accountAddress: string, amount: bigint): Promise { + const keyring = new Keyring({ type: 'sr25519' }); + const alice = keyring.addFromUri('//Alice'); + + const transfer = api.tx.balances.transfer(accountAddress, amount); + await transfer.signAndSend(alice); +} + +export async function connectPolkadot(rpcUrl: string): Promise { + const provider = new WsProvider(rpcUrl); + const api = await ApiPromise.create({ provider }); + await api.isReady; + return api; +} + +export async function transferFunds(rpcUrl: string, paymentAccount: string, amount: number, assetId?: number) { + const provider = new WsProvider(rpcUrl); + const api = await ApiPromise.create({ provider }); + const keyring = new Keyring({ type: 'sr25519' }); + const sender = keyring.addFromUri('//Alice'); + let transfer; + let signerOptions = {}; + + await cryptoWaitReady(); + + if (assetId) { + const adjustedAmount = amount * Math.pow(10, 6); + + transfer = api.tx.assets.transfer(assetId, paymentAccount, adjustedAmount); + signerOptions = { + tip: 0, + assetId: { parents: 0, interior: { X2: [{ palletInstance: 50 }, { generalIndex: assetId }] } } + }; + } else { + const adjustedAmount = amount * Math.pow(10, 10); + + transfer = api.tx.balances.transferKeepAlive(paymentAccount, adjustedAmount); + } + + const unsub = await transfer.signAndSend(sender, signerOptions, async ({ status }) => { + if (status.isInBlock || status.isFinalized) { + unsub(); + } + }); + + // Wait for transaction to be included in block + await new Promise(resolve => setTimeout(resolve, 8000)); +} diff --git a/tests/kalatori-api-test-suite/tests/order.test.ts b/tests/kalatori-api-test-suite/tests/order.test.ts new file mode 100644 index 0000000..290edd2 --- /dev/null +++ b/tests/kalatori-api-test-suite/tests/order.test.ts @@ -0,0 +1,310 @@ +import request from 'supertest'; +import { connectPolkadot, transferFunds } from '../src/polkadot'; +import { ApiPromise } from '@polkadot/api'; + +describe('Order Endpoint Blackbox Tests', () => { + const baseUrl = process.env.DAEMON_HOST; + if (!baseUrl ) { + throw new Error('check all environment variables are defined'); + } + const dotOrderData = { + amount: 1, + currency: 'DOT', + callback: 'https://example.com/callback' + }; + + const usdcOrderData = { + amount: 1, + currency: 'USDC', + callback: 'https://example.com/callback' + }; + + const invalidOrderAmount = { + amount: -1, + currency: 'DOT', + callback: 'https://example.com/callback' + }; + + const missingOrderAmount = { + currency: 'DOT', + callback: 'https://example.com/callback' + }; + + const invalidOrderCurrency = { + amount: 1, + currency: 'INVALID', + callback: 'https://example.com/callback' + }; + + const missingOrderCurrency = { + amount: 1, + currency: 'INVALID', + callback: 'https://example.com/callback' + }; + + const checkOrder = (orderId: any, orderResponseObject:any, orderData: any) => { + expect(orderResponseObject).toHaveProperty('order', orderId); + expect(orderResponseObject).toHaveProperty('message', ''); + expect(orderResponseObject).toHaveProperty('recipient'); + expect(orderResponseObject).toHaveProperty('server_info'); + expect(orderResponseObject).toHaveProperty('withdrawal_status', 'waiting'); + expect(orderResponseObject).toHaveProperty('payment_status', 'pending'); + expect(orderResponseObject).toHaveProperty('amount', orderData.amount); + + expect(orderResponseObject).toHaveProperty('callback', orderData.callback); + expect(orderResponseObject).toHaveProperty('transactions'); + expect(Array.isArray(orderResponseObject.transactions)).toBe(true); + expect(orderResponseObject).toHaveProperty('payment_account'); + expect(orderResponseObject).toHaveProperty('death'); + expect(orderResponseObject).toHaveProperty('payment_page', ''); + expect(orderResponseObject).toHaveProperty('redirect_url', ''); + + expect(orderResponseObject.server_info).toHaveProperty('version'); + expect(orderResponseObject.server_info).toHaveProperty('instance_id'); + expect(orderResponseObject.server_info).toHaveProperty('debug', true); + } + + const generateRandomOrderId = () => { + return `order_${Math.random().toString(36).substring(2, 15)}`; + } + + const createOrder = async (orderId: string, orderData: any, expectedStatus: number = 201) => { + const response = await request(baseUrl) + .post(`/v2/order/${orderId}`) + .send(orderData); + expect(response.status).toBe(expectedStatus); + + return response.body; + }; + + const getOrderDetails = async (orderId: string) => { + const response = await request(baseUrl) + .post(`/v2/order/${orderId}`); + expect(response.status).toBe(200); + return response.body; + }; + + it('should create a new DOT order', async () => { + const orderId = generateRandomOrderId(); + const createdOrder = await createOrder(orderId, dotOrderData); + checkOrder(orderId, createdOrder, dotOrderData); + + expect(createdOrder).toHaveProperty('currency'); + expect(createdOrder.currency).toHaveProperty('currency', dotOrderData.currency); + expect(createdOrder.currency).toHaveProperty('chain_name', 'polkadot'); + expect(createdOrder.currency).toHaveProperty('kind', 'native'); + expect(createdOrder.currency).toHaveProperty('decimals', 10); + expect(createdOrder.currency).toHaveProperty('rpc_url'); + }); + + it('should create a new USDC order', async () => { + const orderId = generateRandomOrderId(); + const createdOrder = await createOrder(orderId, usdcOrderData); + checkOrder(orderId, createdOrder, usdcOrderData); + + expect(createdOrder).toHaveProperty('currency'); + expect(createdOrder.currency).toHaveProperty('currency', usdcOrderData.currency); + expect(createdOrder.currency).toHaveProperty('chain_name', 'statemint'); + expect(createdOrder.currency).toHaveProperty('kind', 'asset'); + expect(createdOrder.currency).toHaveProperty('decimals', 6); + expect(createdOrder.currency).toHaveProperty('rpc_url'); + expect(createdOrder.currency).toHaveProperty('asset_id', 1337); + }); + + it('should return 400 for invalid amount', async () => { + const orderId = generateRandomOrderId(); + const response = await request(baseUrl) + .post(`/v2/order/${orderId}`) + .send(invalidOrderAmount); + + expect(response.status).toBe(400); + expect(response.body[0]).toHaveProperty('parameter', 'amount'); + expect(response.body[0]).toHaveProperty('message', expect.stringContaining('less than the currency\'s existential deposit')); + }); + + it('should return 400 for missing amount', async () => { + const orderId = generateRandomOrderId(); + const response = await request(baseUrl) + .post(`/v2/order/${orderId}`) + .send(missingOrderAmount); + + expect(response.status).toBe(400); + expect(response.body[0]).toHaveProperty('parameter', 'amount'); + expect(response.body[0]).toHaveProperty('message', expect.stringContaining('parameter wasn\'t found')); + }); + + it('should return 400 for invalid currency', async () => { + const orderId = generateRandomOrderId(); + const response = await request(baseUrl) + .post(`/v2/order/${orderId}`) + .send(invalidOrderCurrency); + + expect(response.status).toBe(400); + expect(response.body[0]).toHaveProperty('parameter', 'currency'); + expect(response.body[0]).toHaveProperty('message', 'provided currency isn\'t supported'); + }); + + it('should return 400 for missing currency', async () => { + const orderId = generateRandomOrderId(); + const response = await request(baseUrl) + .post(`/v2/order/${orderId}`) + .send(missingOrderCurrency); + + expect(response.status).toBe(400); + expect(response.body[0]).toHaveProperty('parameter', 'currency'); + expect(response.body[0]).toHaveProperty('message', 'provided currency isn\'t supported'); + }); + + it('should update existing DOT order to be USDC', async () => { + const orderId = generateRandomOrderId(); + const createdOrder = await createOrder(orderId, dotOrderData); + checkOrder(orderId, createdOrder, dotOrderData); + + expect(createdOrder).toHaveProperty('currency'); + expect(createdOrder.currency).toHaveProperty('currency', dotOrderData.currency); + expect(createdOrder.currency).toHaveProperty('chain_name', 'polkadot'); + expect(createdOrder.currency).toHaveProperty('kind', 'native'); + expect(createdOrder.currency).toHaveProperty('decimals', 10); + expect(createdOrder.currency).toHaveProperty('rpc_url'); + + await new Promise(resolve => setTimeout(resolve, 1000)); + + const updatedOrder = await createOrder(orderId, usdcOrderData, 200); + + expect(updatedOrder).toHaveProperty('currency'); + expect(updatedOrder.currency).toHaveProperty('currency', usdcOrderData.currency); + expect(updatedOrder.currency).toHaveProperty('chain_name', 'statemint'); + expect(updatedOrder.currency).toHaveProperty('kind', 'asset'); + expect(updatedOrder.currency).toHaveProperty('decimals', 6); + expect(updatedOrder.currency).toHaveProperty('rpc_url'); + }); + + it('should get DOT order details', async () => { + const orderId = generateRandomOrderId(); + await createOrder(orderId, dotOrderData); + const orderDetails = await getOrderDetails(orderId); + + checkOrder(orderId, orderDetails, dotOrderData); + + expect(orderDetails).toHaveProperty('currency'); + expect(orderDetails.currency).toHaveProperty('currency', dotOrderData.currency); + expect(orderDetails.currency).toHaveProperty('chain_name', 'polkadot'); + expect(orderDetails.currency).toHaveProperty('kind', 'native'); + expect(orderDetails.currency).toHaveProperty('decimals', 10); + expect(orderDetails.currency).toHaveProperty('rpc_url'); + }); + + it('should get USDC order details', async () => { + const orderId = generateRandomOrderId(); + await createOrder(orderId, usdcOrderData); + const orderDetails = await getOrderDetails(orderId); + checkOrder(orderId, orderDetails, usdcOrderData); + + expect(orderDetails).toHaveProperty('currency'); + expect(orderDetails.currency).toHaveProperty('currency', usdcOrderData.currency); + expect(orderDetails.currency).toHaveProperty('chain_name', 'statemint'); + expect(orderDetails.currency).toHaveProperty('kind', 'asset'); + expect(orderDetails.currency).toHaveProperty('decimals', 6); + expect(orderDetails.currency).toHaveProperty('rpc_url'); + expect(orderDetails.currency).toHaveProperty('asset_id', 1337); + }); + + it('should return 404 for non-existing order on get order', async () => { + const nonExistingOrderId = 'nonExistingOrder123'; + const response = await request(baseUrl) + .post(`/v2/order/${nonExistingOrderId}`); + expect(response.status).toBe(404); + }); + + it.skip('should create, repay, and automatically withdraw an order in DOT', async () => { + const orderId = generateRandomOrderId(); + await createOrder(orderId, dotOrderData); + const orderDetails = await getOrderDetails(orderId); + const paymentAccount = orderDetails.payment_account; + expect(paymentAccount).toBeDefined(); + + await transferFunds(orderDetails.currency.rpc_url, paymentAccount, dotOrderData.amount); + + const repaidOrderDetails = await getOrderDetails(orderId); + expect(repaidOrderDetails.payment_status).toBe('paid'); + expect(repaidOrderDetails.withdrawal_status).toBe('completed'); + }, 30000); + + it.skip('should create, repay, and automatically withdraw an order in USDC', async () => { + const orderId = generateRandomOrderId(); + await createOrder(orderId, usdcOrderData); + const orderDetails = await getOrderDetails(orderId); + const paymentAccount = orderDetails.payment_account; + expect(paymentAccount).toBeDefined(); + + await transferFunds( + orderDetails.currency.rpc_url, + paymentAccount, + usdcOrderData.amount, + orderDetails.currency.asset_id + ); + + const repaidOrderDetails = await getOrderDetails(orderId); + expect(repaidOrderDetails.payment_status).toBe('paid'); + expect(repaidOrderDetails.withdrawal_status).toBe('completed'); + }, 30000); + + it.skip('should not automatically withdraw an order until fully repaid', async () => { + const orderId = generateRandomOrderId(); + await createOrder(orderId, usdcOrderData); + const orderDetails = await getOrderDetails(orderId); + const paymentAccount = orderDetails.payment_account; + expect(paymentAccount).toBeDefined(); + + const halfAmount = orderDetails.amount/2; + + // Partial repayment + await transferFunds( + orderDetails.currency.rpc_url, + paymentAccount, + halfAmount, + orderDetails.currency.asset_id + ); + let repaidOrderDetails = await getOrderDetails(orderId); + expect(repaidOrderDetails.payment_status).toBe('pending'); + expect(repaidOrderDetails.withdrawal_status).toBe('waiting'); + + // Full repayment + await transferFunds( + orderDetails.currency.rpc_url, + paymentAccount, + halfAmount, + orderDetails.currency.asset_id + ); + repaidOrderDetails = await getOrderDetails(orderId); + expect(repaidOrderDetails.payment_status).toBe('paid'); + expect(repaidOrderDetails.withdrawal_status).toBe('completed'); + }, 30000); + + it.skip('should not update order if received payment in wrong currency', async () => { + const orderId = generateRandomOrderId(); + await createOrder(orderId, usdcOrderData); + const orderDetails = await getOrderDetails(orderId); + const paymentAccount = orderDetails.payment_account; + expect(paymentAccount).toBeDefined(); + + const assetId = 1984; // Different asset ID to simulate wrong currency + await transferFunds( + orderDetails.currency.rpc_url, + paymentAccount, + usdcOrderData.amount, + assetId + ); + + const repaidOrderDetails = await getOrderDetails(orderId); + expect(repaidOrderDetails.payment_status).toBe('pending'); + expect(repaidOrderDetails.withdrawal_status).toBe('waiting'); + }, 30000); + + it.skip('should return 404 for non-existing order on force withdrawal', async () => { + const nonExistingOrderId = 'nonExistingOrder123'; + const response = await request(baseUrl) + .post(`/v2/order/${nonExistingOrderId}/forceWithdrawal`); + expect(response.status).toBe(404); + }); +}); diff --git a/tests/kalatori-api-test-suite/tests/status.test.ts b/tests/kalatori-api-test-suite/tests/status.test.ts new file mode 100644 index 0000000..e26b477 --- /dev/null +++ b/tests/kalatori-api-test-suite/tests/status.test.ts @@ -0,0 +1,105 @@ +import request from 'supertest'; + +describe('Blackbox API Tests', () => { + const baseUrl = process.env.DAEMON_HOST; + if (!baseUrl) { + throw new Error('DAEMON_HOST environment variable is not defined'); + } + + it('should return server status with valid server_info and supported_currencies', async () => { + const response = await request(baseUrl).get('/v2/status'); + + expect(response.status).toBe(200); + + // Validate server_info properties + expect(response.body).toHaveProperty('server_info'); + expect(response.body.server_info).toHaveProperty('version'); + expect(response.body.server_info).toHaveProperty('instance_id'); + expect(response.body.server_info).toHaveProperty('debug'); + expect(response.body.server_info.debug).toBe(true); + expect(response.body.server_info).toHaveProperty('kalatori_remark'); + + // Validate supported_currencies properties + expect(response.body).toHaveProperty('supported_currencies'); + + const expectedCurrencies = { + DOT: { + chain_name: 'polkadot', + decimals: 10, + kind: 'native', + rpc_url: 'wss://1rpc.io/dot', + ss58: 0, + }, + USDC: { + asset_id: 1337, + chain_name: 'statemint', + decimals: 6, + kind: 'asset', + rpc_url: 'wss://statemint-rpc.dwellir.com', + ss58: 0, + }, + USDt: { + asset_id: 1984, + chain_name: 'statemint', + decimals: 6, + kind: 'asset', + rpc_url: 'wss://statemint-rpc.dwellir.com', + ss58: 0, + }, + }; + + for (const currency in expectedCurrencies) { + if (expectedCurrencies.hasOwnProperty(currency)) { + const currencyKey = currency as keyof typeof expectedCurrencies; + expect(response.body.supported_currencies).toHaveProperty(currency); + expect(response.body.supported_currencies[currency]).toHaveProperty('chain_name', expectedCurrencies[currencyKey].chain_name); + expect(response.body.supported_currencies[currency]).toHaveProperty('decimals', expectedCurrencies[currencyKey].decimals); + expect(response.body.supported_currencies[currency]).toHaveProperty('rpc_url'); + + // Check if asset_id exists in the expected currency and then validate it + if ('asset_id' in expectedCurrencies[currencyKey]) { + expect(response.body.supported_currencies[currency]).toHaveProperty('asset_id', expectedCurrencies[currencyKey].asset_id); + } + + expect(response.body.supported_currencies[currency]).toHaveProperty('ss58', expectedCurrencies[currencyKey].ss58); + } + } + }); + + it('should return valid health status with at least one connected RPC and dynamic instance_id', async () => { + const response = await request(baseUrl).get('/v2/health'); + + expect(response.status).toBe(200); + + // Validate server_info properties + expect(response.body).toHaveProperty('server_info'); + expect(response.body.server_info).toHaveProperty('version'); + expect(response.body.server_info).toHaveProperty('instance_id'); + expect(response.body.server_info).toHaveProperty('debug'); + expect(response.body.server_info.debug).toBe(true); + expect(response.body.server_info).toHaveProperty('kalatori_remark'); + + const instanceId = response.body.server_info.instance_id; + const instanceIdWords = instanceId.split('-'); + expect(instanceIdWords.length).toBe(2); + + expect(response.body).toHaveProperty('connected_rpcs'); + expect(Array.isArray(response.body.connected_rpcs)).toBe(true); + expect(response.body.connected_rpcs.length).toBeGreaterThan(0); + + let atLeastOneRpcConnected = false; + response.body.connected_rpcs.forEach((rpc: { rpc_url: string; chain_name: string; status: string }) => { + expect(rpc).toHaveProperty('rpc_url'); + expect(rpc).toHaveProperty('chain_name'); + expect(rpc).toHaveProperty('status'); + if (rpc.status === 'ok') { + // at least one RPC should be connected + atLeastOneRpcConnected = true; + } + }); + + expect(atLeastOneRpcConnected).toBe(true); + + expect(response.body).toHaveProperty('status'); + }); +}); diff --git a/tests/kalatori-api-test-suite/tsconfig.json b/tests/kalatori-api-test-suite/tsconfig.json new file mode 100644 index 0000000..8cd43a5 --- /dev/null +++ b/tests/kalatori-api-test-suite/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist" + }, + "include": ["src/**/*.ts", "tests/**/*.ts"] +} diff --git a/tests/kalatori-api-test-suite/yarn.lock b/tests/kalatori-api-test-suite/yarn.lock new file mode 100644 index 0000000..58e01d3 --- /dev/null +++ b/tests/kalatori-api-test-suite/yarn.lock @@ -0,0 +1,3003 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/compat-data@^7.25.2": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" + integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77" + integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.0" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-module-transforms" "^7.25.2" + "@babel/helpers" "^7.25.0" + "@babel/parser" "^7.25.0" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.2" + "@babel/types" "^7.25.2" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.25.0", "@babel/generator@^7.25.4", "@babel/generator@^7.7.2": + version "7.25.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.5.tgz#b31cf05b3fe8c32d206b6dad03bb0aacbde73450" + integrity sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w== + dependencies: + "@babel/types" "^7.25.4" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c" + integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== + dependencies: + "@babel/compat-data" "^7.25.2" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6" + integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.2" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helpers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.0.tgz#e69beb7841cb93a6505531ede34f34e6a073650a" + integrity sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw== + dependencies: + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.25.0", "@babel/parser@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.4.tgz#af4f2df7d02440286b7de57b1c21acfb2a6f257a" + integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA== + dependencies: + "@babel/types" "^7.25.4" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz#04db9ce5a9043d9c635e75ae7969a2cd50ca97ff" + integrity sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/template@^7.25.0", "@babel/template@^7.3.3": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" + integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/traverse@^7.24.7", "@babel/traverse@^7.25.2": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.4.tgz#648678046990f2957407e3086e97044f13c3e18e" + integrity sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.4" + "@babel/parser" "^7.25.4" + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.4" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.4", "@babel/types@^7.3.3": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.4.tgz#6bcb46c72fdf1012a209d016c07f769e10adcb5f" + integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@noble/curves@^1.3.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.5.0.tgz#7a9b9b507065d516e6dce275a1e31db8d2a100dd" + integrity sha512-J5EKamIHnKPyClwVrzmaf5wSdQXgdHcPZIZLu3bwnbeCx8/7NPK5q2ZBWF+5FvYGByjiQQsJYX6jfgB2wDPn3A== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/hashes@1.4.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@polkadot-api/json-rpc-provider-proxy@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz#6e191f28e7d0fbbe8b540fc51d12a0adaeba297e" + integrity sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg== + +"@polkadot-api/json-rpc-provider@0.0.1", "@polkadot-api/json-rpc-provider@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz#333645d40ccd9bccfd1f32503f17e4e63e76e297" + integrity sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA== + +"@polkadot-api/metadata-builders@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz#007f158c9e0546cf79ba440befc0c753ab1a6629" + integrity sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg== + dependencies: + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/observable-client@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz#fd91efee350595a6e0ecfd3f294cc80de86c0cf7" + integrity sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug== + dependencies: + "@polkadot-api/metadata-builders" "0.3.2" + "@polkadot-api/substrate-bindings" "0.6.0" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/substrate-bindings@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz#889b0c3ba19dc95282286506bf6e370a43ce119a" + integrity sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw== + dependencies: + "@noble/hashes" "^1.3.1" + "@polkadot-api/utils" "0.1.0" + "@scure/base" "^1.1.1" + scale-ts "^1.6.0" + +"@polkadot-api/substrate-client@^0.1.2": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz#7a808e5cb85ecb9fa2b3a43945090a6c807430ce" + integrity sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A== + dependencies: + "@polkadot-api/json-rpc-provider" "0.0.1" + "@polkadot-api/utils" "0.1.0" + +"@polkadot-api/utils@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@polkadot-api/utils/-/utils-0.1.0.tgz#d36937cdc465c2ea302f3278cf53157340ab33a0" + integrity sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA== + +"@polkadot/api-augment@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-12.4.2.tgz#6c52a6d04f398e786a834839948b0bc0069b391c" + integrity sha512-BkG2tQpUUO0iUm65nSqP8hwHkNfN8jQw8apqflJNt9H8EkEL6v7sqwbLvGqtlxM9wzdxbg7lrWp3oHg4rOP31g== + dependencies: + "@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.3" + +"@polkadot/api-base@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-12.4.2.tgz#c8312bae8dfc70c0fdec0c1366e405906e66575f" + integrity sha512-XYI7Po8i6C4lYZah7Xo0v7zOAawBUfkmtx0YxsLY/665Sup8oqzEj666xtV9qjBzR9coNhQonIFOn+9fh27Ncw== + dependencies: + "@polkadot/rpc-core" "12.4.2" + "@polkadot/types" "12.4.2" + "@polkadot/util" "^13.0.2" + rxjs "^7.8.1" + tslib "^2.6.3" + +"@polkadot/api-derive@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-12.4.2.tgz#2a1fbd79ff4842edc20378957374000ca6f7bd70" + integrity sha512-R0AMANEnqs5AiTaiQX2FXCxUlOibeDSgqlkyG1/0KDsdr6PO/l3dJOgEO+grgAwh4hdqzk4I9uQpdKxG83f2Gw== + dependencies: + "@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.3" + +"@polkadot/api@12.4.2", "@polkadot/api@^12.4.1": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-12.4.2.tgz#c13dc1ad7fab670c5fd6d8d970a8462b999d7c1d" + integrity sha512-e1KS048471iBWZU10TJNEYOZqLO+8h8ajmVqpaIBOVkamN7tmacBxmHgq0+IA8VrGxjxtYNa1xF5Sqrg76uBEg== + dependencies: + "@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.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.3" + +"@polkadot/keyring@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-13.0.2.tgz#05a655eb06c965ae5ee5f181d25916797ea50849" + integrity sha512-NeLbhyKDT5W8LI9seWTZGePxNTOVpDhv2018HSrEDwJq9Ie0C4TZhUf3KNERCkSveuThXjfQJMs+1CF33ZXPWw== + dependencies: + "@polkadot/util" "13.0.2" + "@polkadot/util-crypto" "13.0.2" + tslib "^2.6.2" + +"@polkadot/networks@13.0.2", "@polkadot/networks@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-13.0.2.tgz#0f8fc896b8fb2141212b6448739f4a00bc72b29c" + integrity sha512-ABAL+vug/gIwkdFEzeh87JoJd0YKrxSYg/HjUrZ+Zis2ucxQEKpvtCpJ34ku+YrjacBfVqIAkkwd3ZdIPGq9aQ== + dependencies: + "@polkadot/util" "13.0.2" + "@substrate/ss58-registry" "^1.46.0" + tslib "^2.6.2" + +"@polkadot/rpc-augment@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-12.4.2.tgz#fbe310260f3e5159fc2fa924c1a7c52f69162f9c" + integrity sha512-IEco5pnso+fYkZNMlMAN5i4XAxdXPv0PZ0HNuWlCwF/MmRvWl8pq5JFtY1FiByHEbeuHwMIUhHM5SDKQ85q9Hg== + dependencies: + "@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.3" + +"@polkadot/rpc-core@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-12.4.2.tgz#d20cfdadd932978d58037a213115844a0c49464b" + integrity sha512-yaveqxNcmyluyNgsBT5tpnCa/md0CGbOtRK7K82LWsz7gsbh0x80GBbJrQGxsUybg1gPeZbO1q9IigwA6fY8ag== + dependencies: + "@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.3" + +"@polkadot/rpc-provider@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-12.4.2.tgz#c6a4f9b9194a5227e4355cef026aac2b07430162" + integrity sha512-cAhfN937INyxwW1AdjABySdCKhC7QCIONRDHDea1aLpiuxq/w+QwjxauR9fCNGh3lTaAwwnmZ5WfFU2PtkDMGQ== + dependencies: + "@polkadot/keyring" "^13.0.2" + "@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" + eventemitter3 "^5.0.1" + mock-socket "^9.3.1" + nock "^13.5.4" + tslib "^2.6.3" + optionalDependencies: + "@substrate/connect" "0.8.11" + +"@polkadot/types-augment@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-12.4.2.tgz#8b8e278f4cbecbdd586470d31c27576e06e87074" + integrity sha512-3fDCOy2BEMuAtMYl4crKg76bv/0pDNEuzpAzV4EBUMIlJwypmjy5sg3gUPCMcA+ckX3xb8DhkWU4ceUdS7T2KQ== + dependencies: + "@polkadot/types" "12.4.2" + "@polkadot/types-codec" "12.4.2" + "@polkadot/util" "^13.0.2" + tslib "^2.6.3" + +"@polkadot/types-codec@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-12.4.2.tgz#aa601ddbbe4bb28ef751e4565bd87037dee9a49b" + integrity sha512-DiPGRFWtVMepD9i05eC3orSbGtpN7un/pXOrXu0oriU+oxLkpvZH68ZsPNtJhKdQy03cAYtvB8elJOFJZYqoqQ== + dependencies: + "@polkadot/util" "^13.0.2" + "@polkadot/x-bigint" "^13.0.2" + tslib "^2.6.3" + +"@polkadot/types-create@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-12.4.2.tgz#1113746ab92694c3402abc59feb3e3fcaf980997" + integrity sha512-nOpeAKZLdSqNMfzS3waQXgyPPaNt8rUHEmR5+WNv6c/Ke/vyf710wjxiTewfp0wpBgtdrimlgG4DLX1J9Ms1LA== + dependencies: + "@polkadot/types-codec" "12.4.2" + "@polkadot/util" "^13.0.2" + tslib "^2.6.3" + +"@polkadot/types-known@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-12.4.2.tgz#c47ffac0a0bcc544e120f09e92f39e6f61ed94c8" + integrity sha512-bvhO4KQu/dgPmdwQXsweSMRiRisJ7Bp38lZVEIFykfd2qYyRW3OQEbIPKYpx9raD+fDATU0bTiKQnELrSGhYXw== + dependencies: + "@polkadot/networks" "^13.0.2" + "@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.3" + +"@polkadot/types-support@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-12.4.2.tgz#22df5c22a002aca271507355123aeb68e1399c03" + integrity sha512-bz6JSt23UEZ2eXgN4ust6z5QF9pO5uNH7UzCP+8I/Nm85ZipeBYj2Wu6pLlE3Hw30hWZpuPxMDOKoEhN5bhLgw== + dependencies: + "@polkadot/util" "^13.0.2" + tslib "^2.6.3" + +"@polkadot/types@12.4.2": + version "12.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-12.4.2.tgz#948e0191b30c37f0d89b8e120174d6be31ed9f9d" + integrity sha512-ivYtt7hYcRvo69ULb1BJA9BE1uefijXcaR089Dzosr9+sMzvsB1yslNQReOq+Wzq6h6AQj4qex6qVqjWZE6Z4A== + dependencies: + "@polkadot/keyring" "^13.0.2" + "@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.3" + +"@polkadot/util-crypto@13.0.2", "@polkadot/util-crypto@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-13.0.2.tgz#fee602bcb39e9424300410f4144f170ee2a29292" + integrity sha512-woUsJJ6zd/caL7U+D30a5oM/+WK9iNI00Y8aNUHSj6Zq/KPzK9uqDBaLGWwlgrejoMQkxxiU2X0f2LzP15AtQg== + dependencies: + "@noble/curves" "^1.3.0" + "@noble/hashes" "^1.3.3" + "@polkadot/networks" "13.0.2" + "@polkadot/util" "13.0.2" + "@polkadot/wasm-crypto" "^7.3.2" + "@polkadot/wasm-util" "^7.3.2" + "@polkadot/x-bigint" "13.0.2" + "@polkadot/x-randomvalues" "13.0.2" + "@scure/base" "^1.1.5" + tslib "^2.6.2" + +"@polkadot/util@13.0.2", "@polkadot/util@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-13.0.2.tgz#f0a2572d74730fda8dfd690b60d53c131a688f3b" + integrity sha512-/6bS9sfhJLhs8QuqWaR1eRapzfDdGC5XAQZEPL9NN5sTTA7HxWos8rVleai0UERm8QUMabjZ9rK9KpzbXl7ojg== + dependencies: + "@polkadot/x-bigint" "13.0.2" + "@polkadot/x-global" "13.0.2" + "@polkadot/x-textdecoder" "13.0.2" + "@polkadot/x-textencoder" "13.0.2" + "@types/bn.js" "^5.1.5" + bn.js "^5.2.1" + tslib "^2.6.2" + +"@polkadot/wasm-bridge@7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-bridge/-/wasm-bridge-7.3.2.tgz#e1b01906b19e06cbca3d94f10f5666f2ae0baadc" + integrity sha512-AJEXChcf/nKXd5Q/YLEV5dXQMle3UNT7jcXYmIffZAo/KI394a+/24PaISyQjoNC0fkzS1Q8T5pnGGHmXiVz2g== + dependencies: + "@polkadot/wasm-util" "7.3.2" + tslib "^2.6.2" + +"@polkadot/wasm-crypto-asmjs@7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.3.2.tgz#c6d41bc4b48b5359d57a24ca3066d239f2d70a34" + integrity sha512-QP5eiUqUFur/2UoF2KKKYJcesc71fXhQFLT3D4ZjG28Mfk2ZPI0QNRUfpcxVQmIUpV5USHg4geCBNuCYsMm20Q== + dependencies: + tslib "^2.6.2" + +"@polkadot/wasm-crypto-init@7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.3.2.tgz#7e1fe79ba978fb0a4a0f74a92d976299d38bc4b8" + integrity sha512-FPq73zGmvZtnuJaFV44brze3Lkrki3b4PebxCy9Fplw8nTmisKo9Xxtfew08r0njyYh+uiJRAxPCXadkC9sc8g== + dependencies: + "@polkadot/wasm-bridge" "7.3.2" + "@polkadot/wasm-crypto-asmjs" "7.3.2" + "@polkadot/wasm-crypto-wasm" "7.3.2" + "@polkadot/wasm-util" "7.3.2" + tslib "^2.6.2" + +"@polkadot/wasm-crypto-wasm@7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.3.2.tgz#44e08ed5cf6499ce4a3aa7247071a5d01f6a74f4" + integrity sha512-15wd0EMv9IXs5Abp1ZKpKKAVyZPhATIAHfKsyoWCEFDLSOA0/K0QGOxzrAlsrdUkiKZOq7uzSIgIDgW8okx2Mw== + dependencies: + "@polkadot/wasm-util" "7.3.2" + tslib "^2.6.2" + +"@polkadot/wasm-crypto@^7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-7.3.2.tgz#61bbcd9e591500705c8c591e6aff7654bdc8afc9" + integrity sha512-+neIDLSJ6jjVXsjyZ5oLSv16oIpwp+PxFqTUaZdZDoA2EyFRQB8pP7+qLsMNk+WJuhuJ4qXil/7XiOnZYZ+wxw== + dependencies: + "@polkadot/wasm-bridge" "7.3.2" + "@polkadot/wasm-crypto-asmjs" "7.3.2" + "@polkadot/wasm-crypto-init" "7.3.2" + "@polkadot/wasm-crypto-wasm" "7.3.2" + "@polkadot/wasm-util" "7.3.2" + tslib "^2.6.2" + +"@polkadot/wasm-util@7.3.2", "@polkadot/wasm-util@^7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-util/-/wasm-util-7.3.2.tgz#4fe6370d2b029679b41a5c02cd7ebf42f9b28de1" + integrity sha512-bmD+Dxo1lTZyZNxbyPE380wd82QsX+43mgCm40boyKrRppXEyQmWT98v/Poc7chLuskYb6X8IQ6lvvK2bGR4Tg== + dependencies: + tslib "^2.6.2" + +"@polkadot/x-bigint@13.0.2", "@polkadot/x-bigint@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-13.0.2.tgz#25adca9ce0c5ed691f9bced283f44f7e7d824300" + integrity sha512-h2jKT/UaxiEal8LhQeH6+GCjO7GwEqVAD2SNYteCOXff6yNttqAZYJuHZsndbVjVNwqRNf8D5q/zZkD0HUd6xQ== + dependencies: + "@polkadot/x-global" "13.0.2" + tslib "^2.6.2" + +"@polkadot/x-fetch@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-13.0.2.tgz#841d901fae36cbc4157297324ca0d73fbe4d200e" + integrity sha512-B/gf9iriUr6za/Ui7zIFBfHz7UBZ68rJEIteWHx1UHRCZPcLqv+hgpev6xIGrkfFljI0/lI7IwtN2qy6HYzFBg== + dependencies: + "@polkadot/x-global" "13.0.2" + node-fetch "^3.3.2" + tslib "^2.6.2" + +"@polkadot/x-global@13.0.2", "@polkadot/x-global@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-13.0.2.tgz#77afc4fbd4cfac8ba78cf120836f30ecc7322a74" + integrity sha512-OoNIXLB5y8vIKpk4R+XmpDPhipNXWSUvEwUnpQT7NAxNLmzgMq1FhbrwBWWPRNHPrQonp7mqxV/X+v5lv1HW/g== + dependencies: + tslib "^2.6.2" + +"@polkadot/x-randomvalues@13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-13.0.2.tgz#78ae28b345895cc816ffcad0b336c31cadfcf928" + integrity sha512-SGj+L0H/7TWZtSmtkWlixO4DFzXDdluI0UscN2h285os2Ns8PnmBbue+iJ8PVSzpY1BOxd66gvkkpboPz+jXFQ== + dependencies: + "@polkadot/x-global" "13.0.2" + tslib "^2.6.2" + +"@polkadot/x-textdecoder@13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-13.0.2.tgz#662a6855af8e7a5af17f86890e59ab44f829243a" + integrity sha512-mauglOkTJxLGmLwLc3J5Jlq/W+SHP53eiy3F8/8JxxfnXrZKgWoQXGpvXYPjFnMZj0MzDSy/6GjyGWnDCgdQFA== + dependencies: + "@polkadot/x-global" "13.0.2" + tslib "^2.6.2" + +"@polkadot/x-textencoder@13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-13.0.2.tgz#5e178e0f759df50592e6870346c8db2a445af957" + integrity sha512-Lq08H2OnVXj97uaOwg7tcmRS7a4VJYkHEeWO4FyEMOk6P6lU6W8OVNjjxG0se9PCEgmyZPUDbJI//1ynzP4cXw== + dependencies: + "@polkadot/x-global" "13.0.2" + tslib "^2.6.2" + +"@polkadot/x-ws@^13.0.2": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-13.0.2.tgz#d0392a87adcba851a44fc6f7f56792e529228f3e" + integrity sha512-nC5e2eY5D5ZR5teQOB7ib+dWLbmNws86cTz3BjKCalSMBBIn6i3V9ElgABpierBmnSJe9D94EyrH1BxdVfDxUg== + dependencies: + "@polkadot/x-global" "13.0.2" + tslib "^2.6.2" + ws "^8.16.0" + +"@scure/base@^1.1.1", "@scure/base@^1.1.5": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" + integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@substrate/connect-extension-protocol@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.0.0.tgz#badaa6e6b5f7c7d56987d778f4944ddb83cd9ea7" + integrity sha512-nKu8pDrE3LNCEgJjZe1iGXzaD6OSIDD4Xzz/yo4KO9mQ6LBvf49BVrt4qxBFGL6++NneLiWUZGoh+VSd4PyVIg== + +"@substrate/connect-known-chains@^1.1.5": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@substrate/connect-known-chains/-/connect-known-chains-1.3.0.tgz#bc8dc2437e46b3701b64526c90e1de720a1605d8" + integrity sha512-BHcWdhOsnHtoWuS4LpFpH3MbLAhm1amq4hvl5ctI47KNZcZJcEPAF4zmeaTMuvj+UJ7LEFooy46Mn7zok47MwA== + +"@substrate/connect@0.8.11": + version "0.8.11" + resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.8.11.tgz#983ec69a05231636e217b573b8130a6b942af69f" + integrity sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw== + dependencies: + "@substrate/connect-extension-protocol" "^2.0.0" + "@substrate/connect-known-chains" "^1.1.5" + "@substrate/light-client-extension-helpers" "^1.0.0" + smoldot "2.0.26" + +"@substrate/light-client-extension-helpers@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz#7b60368c57e06e5cf798c6557422d12e6d81f1ff" + integrity sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg== + dependencies: + "@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.5" + rxjs "^7.8.1" + +"@substrate/ss58-registry@^1.46.0": + version "1.50.0" + resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.50.0.tgz#2d2a3d060cd4eadd200e4538078461ba73e13d6d" + integrity sha512-mkmlMlcC+MSd9rA+PN8ljGAm5fVZskvVwkXIsbx4NFwaT8kt38r7e9cyDWscG3z2Zn40POviZvEMrJSk+r2SgQ== + +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + +"@types/bn.js@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.5.tgz#2e0dacdcce2c0f16b905d20ff87aedbc6f7b4bf0" + integrity sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A== + dependencies: + "@types/node" "*" + +"@types/cookiejar@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.5.tgz#14a3e83fa641beb169a2dd8422d91c3c345a9a78" + integrity sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q== + +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.5.12": + version "29.5.12" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/methods@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" + integrity sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ== + +"@types/node@*": + version "22.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" + integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== + dependencies: + undici-types "~6.19.2" + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/superagent@^8.1.0": + version "8.1.9" + resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-8.1.9.tgz#28bfe4658e469838ed0bf66d898354bcab21f49f" + integrity sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ== + dependencies: + "@types/cookiejar" "^2.1.5" + "@types/methods" "^1.1.4" + "@types/node" "*" + form-data "^4.0.0" + +"@types/supertest@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-6.0.2.tgz#2af1c466456aaf82c7c6106c6b5cbd73a5e86588" + integrity sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg== + dependencies: + "@types/methods" "^1.1.4" + "@types/superagent" "^8.1.0" + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.33" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" + integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== + dependencies: + "@types/yargs-parser" "*" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +async@^3.2.3: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" + integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.23.1: + version "4.23.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" + integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== + dependencies: + caniuse-lite "^1.0.30001646" + electron-to-chromium "^1.5.4" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + +bs-logger@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001646: + version "1.0.30001653" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz#b8af452f8f33b1c77f122780a4aecebea0caca56" + integrity sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz#677de7ed7efff67cc40c9bf1897fea79d41b5215" + integrity sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +component-emitter@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" + integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cookiejar@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + +dedent@^1.0.0: + version "1.5.3" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" + integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +dezalgo@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" + integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== + dependencies: + asap "^2.0.0" + wrappy "1" + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + +ejs@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== + dependencies: + jake "^10.8.5" + +electron-to-chromium@^1.5.4: + version "1.5.13" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" + integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +escalade@^3.1.1, escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + +filelist@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + dependencies: + minimatch "^5.0.1" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + +formidable@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-3.5.1.tgz#9360a23a656f261207868b1484624c4c8d06ee1a" + integrity sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og== + dependencies: + dezalgo "^1.0.4" + hexoid "^1.0.0" + once "^1.4.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +hasown@^2.0.0, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +hexoid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" + integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== + dependencies: + hasown "^2.0.2" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jake@^10.8.5: + version "10.9.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" + integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== + dependencies: + async "^3.2.3" + chalk "^4.0.2" + filelist "^1.0.4" + minimatch "^3.1.2" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +methods@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^4.0.4: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +mock-socket@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.3.1.tgz#24fb00c2f573c84812aa4a24181bb025de80cc8e" + integrity sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +nock@^13.5.4: + version "13.5.5" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.5.tgz#cd1caaca281d42be17d51946367a3d53a6af3e78" + integrity sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +once@^1.3.0, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== + +qs@^6.11.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +scale-ts@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/scale-ts/-/scale-ts-1.6.0.tgz#e9641093c5a9e50f964ddb1607139034e3e932e9" + integrity sha512-Ja5VCjNZR8TGKhUumy9clVVxcDpM+YFjAnkMuwQy68Hixio3VRRvWdE3g8T/yC+HXA0ZDQl2TGyUmtmbcVl40Q== + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4, semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +smoldot@2.0.26: + version "2.0.26" + resolved "https://registry.yarnpkg.com/smoldot/-/smoldot-2.0.26.tgz#0e64c7fcd26240fbe4c8d6b6e4b9a9aca77e00f6" + integrity sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig== + dependencies: + ws "^8.8.1" + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +superagent@^9.0.1: + version "9.0.2" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-9.0.2.tgz#a18799473fc57557289d6b63960610e358bdebc1" + integrity sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w== + dependencies: + component-emitter "^1.3.0" + cookiejar "^2.1.4" + debug "^4.3.4" + fast-safe-stringify "^2.1.1" + form-data "^4.0.0" + formidable "^3.5.1" + methods "^1.1.2" + mime "2.6.0" + qs "^6.11.0" + +supertest@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/supertest/-/supertest-7.0.0.tgz#cac53b3d6872a0b317980b2b0cfa820f09cd7634" + integrity sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA== + dependencies: + methods "^1.1.2" + superagent "^9.0.1" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-jest@^29.2.4: + version "29.2.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" + integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== + dependencies: + bs-logger "^0.2.6" + ejs "^3.1.10" + fast-json-stable-stringify "^2.1.0" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.6.3" + yargs-parser "^21.1.1" + +tslib@^2.1.0, tslib@^2.6.2, tslib@^2.6.3: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typescript@^5.5.4: + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + +v8-to-istanbul@^9.0.1: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +ws@^8.16.0, ws@^8.8.1: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==